Quel est le rapport entre les pointeurs et les tableaux en langage C?
-----
Quel est le rapport entre les pointeurs et les tableaux en langage C?
Heu.... les adresses... j'ai bon ?
Bonjour à toi, quand même.
Evite les questions ouvertes qui n'apportent que des réponses vagues ou trop longues pour figurer sur un forum. Bref, précise ta question.
Et accessoirement, pense à relire l'article 2 de la Charte du forum.
Lorsqu'on déclare un tableau, par exemple
tab est un pointeur, mais d'une nature particulière puisqu'il s'agit d'un pointeur constant. Pas question de le faire pointer ailleurs par exemple.Code:int tab[5];
sera donc rejeté par le compilateurCode:tab++;
Par contre:
est correct.Code:int* p = tab; p++;
A+
Bonjour,
Tableaux et pointeurs sont deux choses différentes en c (malgré ce qu'on pourrait croire). Un tableau n'est pas un pointeur tout comme un pointeur n'est pas un tableau, la confusion provient du fait que sauf dans certain cas particuliers, une expression de type «tableau de T» est convertie en type «pointeur sur T», cela est décrit dans la norme C99, §6.3.2.1.3 :
Une expression qui a le type «tableau de type» est convertie en une expression de type «pointeur sur type» qui pointe le premier élément du tableau et n'est pas une lvalue sauf si c'est l'argument de l'opérateur sizeof ou du & unaire ou si c'est une chaîne de caractères littérale utilisée pour initialiser un tableau.Except when it is the operand of the sizeof operator or the unary & operator, or is a
string literal used to initialize an array, an expression that has type ‘‘array of type’’ is
converted to an expression with type ‘‘pointer to type’’ that points to the initial element of
the array object and is not an lvalue.
Tout cela est très bien expliqué dans la FAQ c, soit en Français (cf le point 7. Tableaux et pointeurs) soit directement en Anglais.
Jusqu'ici tout va bien...
Un tableau est un espace mémoire, formaté selon le type de variables, où son accès doit être déterminé par un indexe.
L'appel par le label donne toujours l'addresse de base de l'espace mémoire, qui est immodifiable par le programmeur.
Un pointeur est une variable entière non signée qui contient l'addresse d'un espace mémoire, tableau ou autres ...
Considéré comme une variable, le pointeur à l'avantage d'être manipulé par le programmeur (addition, incrémentation, assignement, ...) contrairement au tableau.
Pour éviter tous BUGS, la valeur du pointeur doit impérativement pointer vers une addresse valide, tableaux ou variables...
C'est le plus souvent une variable entière non signée, mais ce peut être une variable plus complexe, comme par exemple un couple d'entiers représentant le numéro de segment de mémoire contenant l'adresse et l'offset de l'adresse pointée dans ce segment.
Bonjour,
J'aurais dit pour éviter certains bugs ...
D'autre part, il est judicieux d'initialiser le pointeur à 0 lors de sa déclaration, pour être sûr qu'il n'ai pas par hasard une valeur utilisable, ce qui donnerait des résultats imprévisibles et pénibles à debugger.
Enfin, on a envisagé ici les variables de type pointeur, mais il en existe d'autres : les pointeurs calculés, par exemple (pour le tableau int tab [5][3]; la valeur tab[3] est un pointeur, constant, qui pointe vers le début de la 4ème ligne du tableau) ; il y a aussi les fonctions, dont le nom est un pointeur qu'on peut par exemple passer en argument à une fonction (exemple qsort) ; les labels, et sûrement d'autres que j'oublie ...
[CODE]Bonjour a tous,
tant qu'on est dans le domaine des tableau et des pointeurs, j'ai un petit exercice que je n'arrive pas a résoudre. Pourtant je ne pense pas en être bien loin mais y'a une erreur quelque part mais ou svp ?
Code:#include <stdio.h> #include <stdlib.h> int sommeTableau(int tableau[], int tailleTableau) { int somme = 0; somme = tableau[0]+ tableau[1]+ tableau[2]+ tableau[3]; return somme; } int main() { int bouc[4] ={12,3,5,30}; printf ("CASE 0 = %d\nCASE 2 = %d\nCASE 3 = %d\nCASE 4 = %d",bouc[0], bouc[1], bouc[2], bouc[3]); sommeTableau(bouc,4); printf ("\nLa somme de toutes les valeurs du tableau = %d"); return 0; }
S'il y a erreur, il serait bon de nous en donner la teneur ...
Quoiqu'il en soit cette ligne:est loin d'être idéale. Ta fonction ne fera correctement son travail que s'il y a 4 valeurs à additionner. Il faut te servir du 2ème paramètre de la fonction pour déterminer e nombre de valeurs à additionner.Code:somme = tableau[0]+ tableau[1]+ tableau[2]+ tableau[3];
A+
Dernière modification par Jack ; 05/10/2012 à 09h35.
moi je sais c facile mais donner la solution là faut pas pousserCode:sommeTableau(bouc,4); printf ("\nLa somme de toutes les valeurs du tableau = %d");
OK merci quand meme pour l'éguillage me manquait la variable recevant le résultat de la fonction (quel imbécile) erreur d'inattention
int resultat;
int bouc[4] ={12,3,5,30};
printf ("CASE 0 = %d\nCASE 2 = %d\nCASE 3 = %d\nCASE 4 = %d",bouc[0], bouc[1], bouc[2], bouc[3]);
resultat = sommeTableau(bouc,4);
printf ("\nLa somme de toutes les valeurs du tableau = %d",resultat);
ou plus simplement:Mais il faudra revoir le code de ta fonction comme je te l'ai dit plus haut.Code:printf ("\nLa somme de toutes les valeurs du tableau = %d",sommeTableau(bouc,4));
A+
ok J'ai réussi a faire a ta manière......
Mais je n'ai pas fini de vous solliciter car j'ai encore besoin d'aide
Avant de commencer le prochain exercice j'aimerais savoir s'il est possible de donner une valeur dans une case d'un tableau (a l'aide d'un scanf par exemple).
ou de demander a l'utilisateur de donner une valeur pour chacune des cases d'un meme tableauCode://Par exemple double Tab[5]={0}; scanf ("%lf", Tab[3]); // c'est a dire demander a l'utilisateur de donner une valeur a la 4 eme case de notre tableau)
En restant toujours dans un niveau moyen (qui est le mien)
Merci pour vos gracieuse aides.....
oui, bien sur. Il ne faut juste pas oublier l'opérateur d'adresse & devant Tab[3]ou de demander a l'utilisateur de donner une valeur pour chacune des cases d'un meme tableau
A+
hum http://fr.wikipedia.org/wiki/Scanf
et donc c quoi une case d'un tableau mmhh c pas un déplacement à partir de l'adresse du tableau
alors soit &(tab[i]) ou ,tab+i)
Je ne vois pas trop où tu veux en venir, ou alors tu confonds adresse et donnée. Il faudra écrireet donc c quoi une case d'un tableau mmhh c pas un déplacement à partir de l'adresse du tableauou bienCode:scanf ("%lf", &Tab+3);.Code:scanf ("%lf", Tab+3);
A+
Dernière modification par Jack ; 05/10/2012 à 18h56.
Excusez moi je me perds un peu
C'est l'adresse de Tab+3&Tab+3
etc'est la valeur de Tab +3Tab+3
on ecrit pas au meme endroit la non ?
Non.
La variable Tab est déclarée comme un tableau, ce qui implique que :
- l'expression « Tab » représente l'adresse de départ du contenu de ce tableau en mémoire,
- l'expression « Tab+3 » représente cette adresse augmentée de 3, c'est-à-dire l'adresse du quatrième élément du tableau.
« &Tab + 3 » et « Tab + 3 » sont donc équivalents.
Si la variable Tab avait été un pointeur, il y aurait eu une différence, car « &Tab » aurait alors représenté l'adresse de ce pointeur (i.e. l'adresse où sa valeur est enregistrée en mémoire) et « Tab » sa valeur (i.e. l'adresse vers laquelle il pointe).
Désolé, erreur de copier coller. Il fallait lire:
Il faudra écrireou bienCode:scanf ("%lf", &Tab[3]);.Code:scanf ("%lf", Tab+3);
Tu es sûr?« &Tab + 3 » et « Tab + 3 » sont donc équivalents.
affiche 2 valeurs différentesCode:printf("%d\n",tab + 3); printf("%d\n",&tab + 3);
A+
Merci ca me rasssure (lol)
J'ai peut-être été un peu vite dans mon affirmation. Au temps pour moi.
Ce qui est vrai, c'est que « &Tab » et « Tab » sont équivalents, et l'explication que j'ai donnée est valable.
En revanche, « &Tab + 3 » et « Tab + 3 » risquent de ne pas être équivalents, parce que le résultat va dépendre de la façon dont le compilateur interprète le « +3 » (et manque de chance, j'ai juste vérifié le calcul dans un des rares cas de figure où les deux expressions étaient égales).
Ainsi, l'expression isolée « Tab + 3 » donne normalement l'adresse du troisième élément du tableau, tandis que l'expression isolée « &Tab + 3 » (lorsqu'elle est acceptée par le compilateur) peut donner l'adresse située 3 fois la taille tu tableau après le début de celui-ci. Et dans les expressions plus complexes incluant « Tab » ou « &Tab » et « +3 », le « +3 » peut aussi être interprété comme l'addition de "3 octets" ou de "3 mots" dans le calcul sur les adresses.
A ce propos, il peut être amusant de compiler et de faire tourner le bout de code suivant sur différentes plateformes :
Code:long tab[4]; printf(" %9d\n", &tab[1]+1 ); printf("-%9d\n", &tab[1] ); printf("__________\n"); printf("=%9d ?\n", (&tab[1]+1)-(&tab[1]) );
Chez moi sur CODE BLOCK ca donne ca:
A quoi sert le 9 entre le % d ?printf(" %9d\n", &tab[1]+1 );
Ca sert à réserver une plage de 9 caractères pour l'affichage, qui sera justifié à droite. Ca permet d'aligner des résultats sur des lignes successives.A quoi sert le 9 entre le % d ?
Le résultat de l'exemple de PA5CAL s'explique par le fait que l'opérateur - utilisé n'est pas celui de l’arithmétique standard, mais de celle des pointeurs, au même titre que le + de &tab[1] + 1.
En conséquence, faire attention aux opérateurs dont le comportement peut être différent selon les données auxquelles ils sont appliqués. je pense en particulier à l'opérateur de division / qui ne fait pas le même calcul sur des entiers et des flottants.
A+
Bonjour,
comme je le précisais dans mon message 5 en citant la norme, tableau et pointeur sont différents surtout quand on utilise sizeof et l'opérateur & unaire :
sizeof donne la taille de la variable passé en paramètre. Cela explique pourquoi sizeof(tab) donne 32 car tab est un tableau de 4 longs (sur ma plateforme long est un entier 64bit), 4x8 = 32, alors que sizeof(ptr) donne simplement 8 (sur ma plateforme, les pointeurs sont définis sur 64 bits).Code:#include <stdio.h> int main() { long tab[4] = {1,2,3,4}; long *ptr = tab; printf("sizeof(tab) = %p\n", sizeof(tab)); printf("sizeof(ptr) = %p\n", sizeof(ptr)); printf("tab = %p\n", tab); printf("tab + 1 = %p\n", tab+1); printf("&tab = %p\n", &tab); printf("&tab + 1 = %p\n", &tab+1); printf("ptr = %p\n", ptr); printf("ptr + 1 = %p\n", ptr+1); return 0; }
dans les printf, tab utilisé comme un pointeur se transforme en pointeur de type "pointeur sur long", cela explique les deux premiers printf, tab est l'adresse du premier long, tab+1 (en arithmétique des pointeurs) renvoie une adresse qui sera à 1 fois le nombre d'octets de la taille des objets pointés (en l'occurence des longs, donc 8 octets).
les deux printf suivants sont différents, &tab n'est pas un pointeur sur des long mais un pointeur sur un tableau de 4 long (donc l'objet pointé a un longueur de 32 octets). tab et &tab ont la même adresse, mais interprétée différemment, tab premier long du tableau, &tab adresse de début du tableau (qui coïncide avec l'adresse du premier long). Si on ajoute 1 à &tab, le compilo voit que le type de &tab est pointeur sur un tableau de 4 long et va donc aller "un tableau plus loin" = + 32 octets.
les derniers printf sont juste les manipulations directes sur les pointeurs et ne devraient pas poser de problèmes.
Le résultat sur ma plateforme donne :
Code:sizeof(tab) = 0x20 sizeof(tab) = 0x8 tab = 0x7fff8dc996b0 tab + 1 = 0x7fff8dc996b8 &tab = 0x7fff8dc996b0 &tab + 1 = 0x7fff8dc996d0 ptr = 0x7fff8dc996b0 ptr + 1 = 0x7fff8dc996b8
excusez moi mais la je suis perdu complet.
vous parlez plus a mon niveau.
jamais encore entendu parler de sizeof