TP0 C ANSI
Les nombres entiers en C / Ansi
Les nombres entiers en C / Ansi
04/11/2024
3H++
Architecture 32 bits et 64 bits.
But
Utilisation de gcc et du debugger , utilisation des entiers, des nombres et des différentes limites des contenants
Les processeurs 32 Bits et 64 bits
char , unsigned char
int , unsigned int
long, unsigned long
float, double
Dans le répertoire /TPC/TP0 qui doit être dans Works dans votre espace sur votre poste de travail et sur idem sur workboot.
Il faut faire sur les 2 cibles !
Après avoir fait one , two , three (répertoires) un exercice un répertoire !! obligatoire !
A la fin de la séance envoyer votre pdf (compte rendu et une archive format tar ! (vu en classe) de votre TP0
Étude des entiers.
Rappel pour compiler utiliser les options du C89 (ANSI)
gcc nom.c -o nom -ansi -pedantic -Wall -g
en gras ce sont des options pour apprendre et faire du C ansi (créé par K&R) (American National Standards Institute)
-g pour utiliser le debugger.
Utiliser gdb le plus souvent possible , pour bien maîtriser cet outil
compte rendu sur "classe"@workboot.fr (votre classe, ciela1 ou ciela1cfa .. )
au format pdf !
Le compte rendu avant la fin de la séance du TP (dans l'état) avec son archive au format tar !
!!! Un exercice (un code) un répertoire par code! et faire référence au code dans votre compte rendu.
Pour tous les exercices il faudra tester gdb et regarder le contenu des variables , et faire du pas à pas, être curieux de ce qu'il se passe dans votre code .
Et utiliser avec gcc les options
-Wall : Warning ALL
-pedantic : conseil pédagogique du compilateur .
-ansi : on va faire du C K&R ou C89
Dans les répertoires Works/TPC/TP0
Prise en mains de la chaîne de compilation c.
Faire l'exemple bonjour le monde vu en cours.
dans un répertoire bonjour ( Works/TPC/TP0/bonjour )
source ci dessous:
#include <stdio.h> /* la librairie standard Input Output */
#include <stdlib.h>
int main(int argc, char **argv)
{
printf("Bonjour le monde ! \n");
return EXIT_SUCCESS;
}
Les exercices doivent être réalisés sur les 2 cibles (workboot arm 32 bits et sur votre pc x86 64 bits sous ubuntu)
Car les résultats seront parfois différents. Et on pourra les justifiers .
non du répertoire : one
nom du source du programme one.c
Ce programme ne fonctionnera pas pareil sur workboot que sur votre machine en local
Donc il faudra exceptionnellement le faire aussi sur votre machine ubuntu/debian du lycée et sur workboot.
la fonction sizeof() donne le nombre d'octets utilisés.
/********************************/
/* donne la taille des types */
/* (o)2024 04/11 Bogt */
/********************************/
#include <stdlib.h> /* librairie standard C prototype et */
#include <stdio.h> /* library standard Input / Output */
int main(int argc, char **argv)
{
printf("Les tailles de variables en octets : \n");
printf("float : %ld en octets\n",sizeof(float));
printf("int : %ld en octets\n",sizeof(int));
printf("short : %ld en octets\n",sizeof(short));
printf("char : %ld en octets\n",sizeof(char));
printf("long : %ld en octets\n",sizeof(long));
printf("int long : %ld en octets\n",sizeof(int long));
printf("int * : %ld en octets\n",sizeof(int *));
return EXIT_SUCCESS;
}
man sizeof ? pour savoir a quoi cela sert !
https://fr.wikipedia.org/wiki/Sizeof
en savoir plus:
https://fr.wikipedia.org/wiki/Types_de_donn%C3%A9e_du_langage_C
En exécutant ce programme conclure sur le résultat obtenu
Justifier votre réponse.
avec la commande arch dans un terminal , regarder sur quel processeur vous travaillez:
sur un processeur 64bits AMD cela donne par exemple:
bruno@bruno-MS-7851:~$ arch
x86_64
bruno@bruno-MS-7851:~$
ou
sur un processeur Arm7 qui n'existe qu'en 32 bits (le ARM8 sera 64bits)
bruno@workboot:~ $ arch
armv7l
bruno@workboot:~ $
sur un processeur ARM 64 bits
bruno@rpi364:~ $ arch
aarch64
sur un processeur RISC V 64 bits
bruno@starfive:~$ arch
riscv64
SUR WORKBOOT : (Raspberry PI , ARM 32 bits)
albert@workboot:~/Works/langage_C/one $ arch
armv7l
albert@workboot:~/Works/langage_C/one $ ./one
Les tailles de variables en octets :
long : 4 en octets
float : 4 en octets
double : 8 en octets
int : 4 en octets
short : 2 en octets
char : 1 en octets
int long : 4 en octets
SUR PC de l'école (INTEL 0x86_ 64bits )
bruno@elliott:~/Works/langage_C/one$ arch
x86_64
bruno@elliott:~/Works/langage_C/one$ ./one
Les tailles de variables en octets :
long : 8 en octets
float : 4 en octets
double : 8 en octets
int : 4 en octets
short : 2 en octets
char : 1 en octets
int long : 8 en octets
Les différents formatages du printf en c
répertoire two dans TP0
qui va contenir : 4 projets (répertoires)
two0
two1
two2
two3
%i : pour afficher en décimal un entier (integer)
%d: pour afficher en décimal (base 10)
%x: Pour afficher en hexadécimal (base 16) (x en minuscule et X en majuscule)
%o: Pour afficher en octal (base 8)
printf est une fonction puissante permettant des affichages formatés
répertoires:
two0 , two1, two2,two3 seront respectivement les exemples utilisant ces formats
├── two0
├── two1
├── two2
├── two3
en déduire ce que permet %d?
en déduire ce que nous donne %o ? ce que ça nous affiche ?
tester les codes selon les affichages ci-dessous
et pour le %x ? ce que ça nous affiche?
/************************ ******/
/* Code entier %d */
/* (c)2021 18/10 Bogt */
/*******************************/
#include <stdlib.h> /* librairie standard C prototype et definitions de fonctions */
#include <stdio.h> /* library standard Input / Output */
int main (int argc , char **argv)
{
int entier;
entier=2018;
printf("le contenu de la variable entier : %d \n",entier);
return EXIT_SUCCESS;
}
/********************************/
/* Code entier %i two1.c */
/* (c)2021 18/10 Bogt */
/********************************/
#include <stdlib.h> /* librairie standart C prototype et definitions de fonctions */
#include <stdio.h> /* library standart Input / Output */
int main (int argc , char **argv)
{
int entier;
entier=2018;
printf("le contenu de la variable entier : %i \n",entier);
return EXIT_SUCCESS;
}
/********************************/
/* Code entier %x two2.c */
/* (c)2021 18/10 Bogt */
/********************************/
#include <stdlib.h> /* librairie standart C prototype et definitions de fonctions */
#include <stdio.h> /* library standart Input / Output */
int main (int argc , char **argv)
{
int entier;
entier=2018;
printf("le contenu de la variable entier : %x \n",entier);
return EXIT_SUCCESS;
}
/********************************/
/* Code entier %o two3.c */
/* (c)2021 18/10 Bogt */
/********************************/
#include <stdlib.h> /* librairie standart C prototype et definitions de fonctions */
#include <stdio.h> /* library standart Input / Output */
int main (int argc , char **argv)
{
int entier;
entier=2018;
printf("le contenu de la variable entier : %o \n",entier);
return EXIT_SUCCESS;
}
Architecture du processeur peut être basée sur une technologie 32 ou 64 bits
void * est ici un pointeur (capable d’accéder a la totalité de la mémoire .
on reverra cette notion plus tard
on peut utiliser un pointeur sur entier
int * ou char * ...
Void est un pointeur sur rien
dans un répertoire three , tester le code
/****************************************************************/
/* le pointeur doit pouvoir parcourir la totalité de la mémoire */
/* Sa taille est fonction de l'architecture de processeur */
/****************************************************************/
#include <stdio.h>
#include <stdlib.h>
int main(int argc,char **argv)
{
/* On vérifie la taille d'un pointeur pour déterminer l'architecture*/
if (sizeof(void*) == 4) {
printf("Le système est en 32 bits.\n");
} else if (sizeof(void*) == 8) {
printf("Le système est en 64 bits.\n");
} else {
printf("Architecture inconnue.\n");
}
return EXIT_SUCCESS;
}
32 bits c'est combien d'octets ?
64 bits c'est combien d'octets ?
Présentation des types :
Trouver les valeurs maximum et minimum que contient un entier.
Un multiplet se compose de 8 bits.
signed
char : min = -128 ; max = 127.
unsigned char : min = 0 ; max = 255.
short : min = -32768 ; max = 32767.
unsigned short : min = 0 ; max = 65535.
int : min = -2147483648 ; max = 2147483647.
unsigned int : min = 0 ; max = 4294967295.
long : min = -9223372036854775808 ; max = 9223372036854775807.
unsigned long : min = 0 ; max = 18446744073709551615.
pour avoir les valeurs vous pouvez utiliser le fichier /usr/include/limits.h
par exemple:
/* Minimum and maximum values a `signed int' can hold. */
# define INT_MIN (-INT_MAX - 1)
# define INT_MAX 2147483647
Le projet sera char (un répertoire char)
/********************************/
/* Code valeurs neg et pos */
/* (c)2021 18/10 Bogt */
/********************************/
#include <stdlib.h>
#include <stdio.h>
int main (int argc , char **argv)
{
char var_char;
var_char =-128; /* tester avec 127,puis 128 et -129 que se passe t'il ? */
printf("le contenu de la variable entier : %d \n",var_char);
return EXIT_SUCCESS;
}
les résultats ne seront pas les même si vous êtes sur arm 32 bits , et intel x86 64 bits
Comment expliquer les résultats :
pour -128
127
128
129
0
1
300
un répertoire long
Même question que la précédente avec le long .
Tester avec un code unitaire
dans un répertoire
uchar
réaliser un programme qui va tester le unsigned char.
Expliquer cette valeur :
sachant que 2^32 = 4294967296 (indice)
aller voir la notation complément à 2.
INT_MAX 2147483647
En plusieurs étapes, découverte de la fonction pseudo aléatoire rand, puis de la modification de sa graine et .. vous emmener à la création d'un Dé Numérique ...
Petit cours pour bien comprendre rand et srand .
Répertoire game_rand
/***********************************/
/* Code un nombre aléatoire(psuedo)*/
/* (c)2021 18/10 Bogt */
/***********************************/
#include<stdio.h>
#include<stdlib.h>
int main (int argc, char**argv)
{
int hasard;
hasard= rand(); /* fonction pseudo aléatoire */
printf ("tada : %d\n",hasard);
return EXIT_SUCCESS;
}
Lancer plusieurs fois ce programme , que constatez vous ?
Le nombre pseudo aléatoire obtenu est compris entre 0 et RAND_MAX
stdlib.h:
#define RAND_MAX 2147483647
Et on désire un nombre entre 0 et 6 comment faire?
Je vous propose d'utiliser la fonction modulo (%)
10%3=1 et 10/3=3
le modulo est le reste de la division entière.
Attention le dé doit fournir un chiffre entre 1 et 6 !
pour initialiser le compteur 'pseudo hasard'
Le temps avance....et change en permanence par définition.
la fonction time(NULL) de la lib time.h
et nous disposons de la fonction clock() aussi
dans un projet temps
/********************************/
/* Code time et clock */
/* (c)2021 18/10 Bogt */
/********************************/
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<unistd.h>
int main (int argc, char**argv)
{
int temps1;
int temps2;
temps1= time(NULL);
printf ("nous sommes : %d\n",temps1);
sleep(1);
temps2=time(NULL);
printf ("apres le sommeil nous sommes : %d \n",temps2);
printf ("Durée : temps2-temps1 = %d \n",temps2-temps1);
return EXIT_SUCCESS;
}
Que fait la fonction sleep ?
Modifier le programme précédent au lieu de time(NULL) utiliser clock()
on ajoute un peu de hasard
dans un projet hasard
/********************************/
/* Code hasard et graine */
/* (c)2021 18/10 Bogt */
/********************************/
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main (int argc, char**argv)
{
int hasard;
srand((unsigned int)clock());
hasard= rand();
printf ("tada : %d\n",hasard);
return EXIT_SUCCESS;
}
Extrait de stdlib.h
/* The largest number rand will return (same as INT_MAX). */
#define RAND_MAX 2147483647
Donc nous disposons de RAND_MAX
c'est la valeur maximale obtenue avec la fonction RAND()
Écrire un programme qui va donner une valeur entre 1 et 6 comme un dé .
on va avoir besoins de calculer le modulo
5/2 = 2 et 5%3 =1
/ : division entère
% : donne le modulo , c'est le reste de la division entière
Rque : 2 x 2 + 1 = 5
Exemple:
./De
4
int main (int argc, char **argv)
/* qu'est ce donc argc ? un entier ! ? */
argc : argument counter
argv : argument value
nous allons découvrir comment fonctionne argc :
non du projet argc (argc.c)
(argc , est la contraction de argument counter)
Écrire un petit programme affichant la valeur entière en décimal de argc .
Tester les valeurs suivantes
./argc un
./argc un deux
./argc un deux trois
./argc 1 2 3 4
./argc un deux 3 quatre 5
./argc 1 2 3 4 5 6
.. etc .. conclure ce que représente argc en francais