====== Tableaux ====== Si vous avez oublié ce qu'est un tableau, vous pouvez aller voir ces explications dans le cours [[nsi:langages:python:tableaux|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 [[nsi:langages:c:pointeurs|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|fonctions]], dans le cas suivant : #include #include 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.