Déclaration d'un tableau de 5 éléments dont les éléments sont de type int
:
int tab[5];
Les indices commencent toujours à 0
, c'est-à-dire le tableau tab
possède les éléments
tab[0],tab[1],tab[2],tab[3],tab[4]
.
Le tableau ci-dessus est déclaré mais il n'est pas initialisé.
Pour initialiser tous les éléments à 0
:
int i;
for(i=0; i < 5; i++)
tab[i]=0;
Notez que nous avons déjà deux occurrences de la constante 5
qui donne la taille du tableau:
dans la définition de tab
et dans la condition de la boucle.
En général
il faut éviter de mettre explicitement les constantes, comme 5
, dans
le code du programme.
On préfère une solution qui utilise une macro:
#define NB_ELEM 5
int tab[NB_ELEM];
int i;
for(i=0; i < NB_ELEM; i++)
tab[i]=0;
Explications:
La ligne
#define NB_ELEM 5
définie une macro-constante NB_ELEM
. Le préprocesseur remplacera dans le texte
du programme toutes les occurrences de NB_ELEM
par la valeur 5
.
Notez que la macro-définition ne se termine pas par un point-virgule.
Déclaration et initialisation d'un tableau.
Il est possible de déclarer et initialiser un tableau en même temps.
La ligne
int tab[] = {-4,6,57,23,-11,4};
déclare un tableau de int
et l'initialise avec les valeurs:
-4,6,57,23,-11,4
. Puisque la liste de valeurs initiales
contient 6
éléments les tableau tab
aura la taille correspondante,
c'est-à-dire 6
.
Il est possible de calculer la taille d'un tableau dans la fonction où le tableau est
défini:
double tab[] = {-4.8, 6.1, 57.0, 23.99, -11.32, 4.5};
int nb_elem, i;
double s = 0;
nb_elem = sizeof(tab)/sizeof(tab[0]);
for(i=0 ; i < nb_elem; i++)
s += tab[i];
L'opérateur sizeof
appliqué au tableau tab
donne sa taille
mesurée en nombre octets occupés par le tableau. Par exemple si la taille d'un élément double
est de
8
octets alors sizeof(tab)
donnera la valeur 6*8 = 48
octets (6
éléments de 8
octets chacun).
sizeof(tab[0])
donne la taille en octet du premier élément du tableau, si un nombre double
occupe 8
octets de la mémoire
alors sizeof(tab[0])
donnera 8
.
Donc l'expression sizeof(tab)/sizeof(tab[0])
donne le nombre d'éléments du tableau tab
.
Avertissement.
Cette méthode de calcul du nombre d'éléments d'un tableau ne s'applique pas pour les tableaux passés par paramètre
dans une fonction.
Pour chaque tableau qui est paramètre d'une fonction on ajoutera un autre paramètre entier qui donne
le nombre d'éléments.
Exemple.
double somme(double tab[], int nb_elem){
int i;
double s;
s=0;
for(i=0 ; i < nb_elem; i++)
s += tab[i];
return s;
}
Cette fonction calcule la somme d'éléments du tableau tab
. Le deuxième paramètre de la fonction,
nb_elem
, est utilisé pour donner le nombre d'éléments de tab
.
A l'intérieur de la fonction somme
l'expression sizeof(tab)/sizeof(tab[0])
donne une valeur qui n'a rien avoir avec le nombre d'éléments du tableau tab
(vous saurez plus sur
l'opérateur sizeof
après les cours sur les pointeurs).
Structures
Définition d'une structure
struct complexe{
double x;
double y;
};
Cela nous définie un nouveau type de données nommé struct complexe
avec deux champs
x
et y
, les deux de type double
.
Déclaration d'une variable et d'un tableau de structures:
#define NB_ELEM 1024
struct complexe a;
struct complexe tab[NB_ELEM];
Pour initialiser la variable a
nous pouvons faire
a.x = 5.12;
a.y = -45.98;
L'opérateur point . permet d'accéder aux champs d'une structure.
Pour initialiser tous les éléments de tab
à 0
nous pouvons écrire
int i;
for(i=0; i < NB_ELEM; i++)
tab[i].x = tab[i].y = 0.0;
Un autre exemple
struct tab_dyn{
int nbelem;
struct complexe tableau[NB_ELEM];
};
Notez qu'il est possible de composer les types,
struct tab_dyn
possède le champs tableau
qui est un tableau de struct complexe
définis auparavant.
Soit
struct tab_dyn t;
La variable t
peut être utilisée comme un tableau dynamique de nombres complexes,
le champs nbelem
donnera l'indice du premier élément libre.
Initialiser le tableau vide revient à faire
t.nbelem = 0;
Ajouter un nouveau élément dans le tableau se fera de façon suivante:
t.tableau[t.nbelem].x = 4.89;
t.tableau[t.nbelem].y = -5.09;
t.nbelem++;
Opérations bit à bit
Nous avons 4 opération bit à bit:
-
&
et logique,
-
|
ou logique,
-
^
ou exclusif,
-
~
négation.
Soit a
et b
deux bits.
Alors
a & b
vaut 1 si les deux bits sont 1. Sinon le résultat est 0.
-
a | b
vaut 1 si au moins un de deux bits est 1. Sinon,
si les deux bits sont 0 le résultat est 0.
-
a ^ b
vaut 1 si un de deux bits et 1 et l'autre 0.
-
~a
donne 1 si a
est 0, et donne 0 si a
est 1.
Notation hexadécimale
Pour travailler avec les bits il est commode d'utiliser les constantes
hexadécimales.
chiffre hexadécimal |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
A |
B |
C |
D |
E |
F |
en binaire |
0000 |
0001 |
0010 |
0011 |
0100 |
0101 |
0110 |
0111 |
1000 |
1001 |
1010 |
1011 |
1100 |
1101 |
1110 |
1111 |
en décimal |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
Donc chaque chiffre hexadécimal donne la valeurs de 4 bits.
Puisque un octet est composé de 8 bits nous avons 2 chiffres hexadécimaux par octet.
Les constantes hexadécimales sont préfixées par 0x
, par exemple Ox11AOF0
Si, par exemple,
int i = 0x11A0F0;
alors, en supposant que sizeof(int)==4
, c'est-à-dire
un int
occupe 4 octets, la valeur de i
en binaire sera
00000000000100011010000011110000
(pour voir plus clair séparons les octets par points:
00000000.00010001.10100000.11110000
ou encore mieux séparons les blocks de 4 bits -
0000.0000.0001.0001.1010.0000.1111.0000
).
Soit maintenant
int j = 1;
La représentation binaire de j
est
00000000000000000000000000000001
(le bit de poids faible 1, tous les autres bits 0).
Maintenant si on fait «ou logique» bit à bit:
int k = i | j;
alors k
aura la valeur
00000000000100011010000011110001
en binaire (les mêmes bits que i
sauf
le dernier qui devient 1).
Par contre «et logique» bit à bit donnera 0.
Décalages à gauche et à droite