Tableaux

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: Soit a et b deux bits. Alors

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