Outils pour utilisateurs

Outils du site


nsi:langages:c:tableaux

Tableaux

Si vous avez oublié ce qu'est un tableau, vous pouvez aller voir ces explications dans le cours Python.

Déclaration

En C, il faut connaître au moment de la compilation la taille du tableau et le type de données qu'il contient. On ne pourra pas mélanger des entiers et des flottants dans un même tableau et on ne pourra pas changer sa taille en cours d'exécution.

Voici comment on déclare un tableau de 6 entiers :

int tableau[6];

Ce code réserve en mémoire l'espace nécessaire pour 6 entiers.

Comme en Python, on pourra lire ou affecter les différentes cases du tableau.

int tableau[6];
tableau[0] = 3;
tableau[2] = 17;
printf("%d", tableau[2]); // affiche 17

En ligne 2 et 3, on écrit dans tableau. En ligne 4, on lit.

Il est possible de déclarer directement le contenu du tableau :

int tableau[6] = {2, 8, 19, 25, 6, 3};

J'insiste, on ne peut pas déclarer

int n;
...
int tableau[n];

Car n pourrait changer de valeur et alors on ne peut pas prévoir à la compilation la taille du tableau. En revanche, ceci est possible :

#define N 100
...
int tableau[N];

car N est une constante et est donc connu au moment de la compilation.

Aspect mémoire

La variable tableau ne contient pas le tableau lui-même mais un pointeur sur le premier élément du tableau, c'est à dire l'adresse mémoire du premier élément du tableau.

On peut s'en convaincre en écrivant dans le main

int tableau[6] = {21, 8, 19, 25, 6, 3};
printf("%d", tableau);
// affiche un nombre entier correspondant à l'adresse mémoire de tableau[0]

Comme tableau est le pointeur, *tableau désigne la valeur pointée, c'est à dire le contenu de la case mémoire pointée par tableau, autrement dit *tableau est identique à tableau[0].

int tableau[6] = {21, 8, 19, 25, 6, 3};
printf("%d", *tableau);
// affiche le contenu de la case mémoire d'adresse tableau
// c'est à dire tableau[0] = 21

Allons plus loin : la case mémoire suivante est à l'adresse tableau + 1 et qu'obtient-on si on regarde son contenu avec *(tableau + 1) ?

int tableau[6] = {21, 8, 19, 25, 6, 3};
printf("%d", *(tableau + 1));
// affiche le contenu de la case mémoire d'adresse tableau + 1
// c'est à dire tableau[1] = 8

Longueur du tableau

Il n'y a pas de fonction len. C'est inutile : on connaît forcément la taille du tableau. Néanmons on peut vouloir connaître la taille d'un tableau qui serait fournit par une autre fonction ou un autre programme par exemple.

La fonction sizeof va fournir la taille mémoire, en octets occupées par le tableau.

int tableau[6] = {21, 8, 19, 25, 6, 3};
int s = sizeof(tableau);
printf("%d", s);
// affiche 24 pour 24 octets

Ce n'est pas très satisfaisant car nous avons un tableau de 6 entiers et nous obtenons une taille de 24 octets… C'est bien-sûr parce que chaque int occupe 4 octets. Pour connaître le nombre de cases mémoires disponibles dans le tableau, on divise donc par la taille d'un entier.

int tableau[6] = {21, 8, 19, 25, 6, 3};
int s = sizeof(tableau)/sizeof(int);
printf("%d", s);
// affiche 24 pour 24 octets

Parcourir un tableau

On utilise une boucle for, par indice (pas d'autre choix)

int tableau[6] = {21, 8, 19, 25, 6, 3};
for (i = 0 ; i < 6 ; i++)
{
    printf("%d\n", tableau[i]);
}

Passer un tableau à une fonction

Supposez que je veuille écrire une fonction affichant le tableau. On doit fournir :

  • tableau qui est un pointeur sur une case mémoire contenant un int donc le type est int *tableau,
  • c'est mieux de fournir la taille du tableau car comme on l'a dit avant, il n'y a pas de méthode simple pour connaître la taille d'un tableau.
void display_tableau(int *tableau, int taille)
{
    for (int i = 0 ; i < taille ; i++)
    {
        printf("%d\n", tableau[i]);
    }
}

Comme vu dans la partie fonctions, dans le cas suivant :

#include <stdio.h>
#include <stdlib.h>

void doubler(int *tableau, int taille)
{
    for (int i = 0 ; i < taille ; i++)
    {
        tableau[i] = 2*tableau[i];
    }
}

int main()
{
   int tableau_exemple[6] = {21, 8, 19, 25, 6, 3};
   doubler(tableau_exemple, 6);
   for (int i = 0 ; i < 6 ; i++)
   {
       printf("%d\n", tableau_exemple[i]);
   }
   return 0;
}

En ligne 15, on appelle doubler avec comme premier argument tableau_exemple. la variable tableau est donc une copie de la variable tableau_exemple.

Faut-il en déduire que les modifications faites dans la fonction doubler n'affecteront pas la variable tableau_exemple ? NON !

En effet, rappelez vous que tableau_exemple est un pointeur, une adresse qui désigne une case mémoire où commence le tableau. Quand tableau devient une copie de tableau_exemple, on fait une copie de ce pointeur. Autrement dit, tableau et tableau_exemple sont deux pointeurs égaux et quoi pointent donc la même case mémoire.

Donc quand on modifie le tableau pointé par tableau, cela modifie aussi le tableau pointé par tableau_exemple car c'est le même tableau.

nsi/langages/c/tableaux.txt · Dernière modification : de goupillwiki