Semaine 11 Les pointeurs (suite) Tableaux et pointeurs Questions sur les pointeurs
Tableaux et pointeurs (1) Tableau = pointeur int tab[3]; → Allocation de 3 cases dans la mémoire tab <=> pointeur vers la première case tab <=> &(tab[0]) NB : en réalité, la variable « tab » n'est pas matérialisée, sauf si c'est un paramètre de fonction tab[i] = la ième valeur après celle pointée par tab Donc tab[0] <=> *tab
Tableaux et pointeurs (2) Tableau paramètre de fonction void f(int tab[]) { … } → c'est le pointeur qui est passé en paramètre, c'est-à- dire l'adresse de la première case du tableau <=> void f(int *tab) { … } → D'où le tableau modifiable par la fonction : quand on passe un tableau en paramètre, on passe en fait l'adresse de la première case. On peut ensuite modifier ce qui se trouve à cette adresse c'est-à-dire le contenu du tableau => Passage par référence → cela explique pourquoi les modifications faites sur un tableau dans une fonction sont répercutées en dehors de la fonction.
Tableaux et pointeurs (3) Tableau paramètre de fonction void ajouteTab(int tab[], int taille, int val){ int i; for(i=0; i < taille; i++){ tab[i] = tab[i] + val; } <=> void ajouteTab(int *tab, int taille, int val){ int i; for(i=0; i < taille; i++){ tab[i] = tab[i] + val; }
Tableaux et pointeurs (4) Tableau résultat de fonction ? int f()[] { … } → erreur: ‘f’ declared as function returning an array → Interdiction de retourner un tableau En revanche une fonction peut retourner un pointeur : Mais l'adresse retournée ne doit pas correspondre à l'adresse d'une variable locale (car sinon la mémoire sera libérée en sortant de la fonction et l'adresse ne correspondra plus à rien). Une autre méthode : procéder à l'allocation dynamique de la mémoire en utilisant malloc et calloc (ne sera pas abordée en LI115 mais en LI215)
Tableaux et pointeurs (5) Tableau = pointeur → pointeur comme résultat de fonction ? NON OUI int *f() { int *f(int *p) { int tab[3]; return (p+1); return tab; } } → attention : cette fonction retourne l'adresse d'une variable locale → Risque très élevé d'erreur lors de l'exécution Au choix: – Erreur de segmentation = le programme cherche à accéder à une partie de la mémoire qui ne lui est pas (plus) allouée – Erreur d'exécution : les données pointées dans le tableau ont été modifiées car la zone mémoire a été utilisée pour une autre portion du programme.
Tableaux et pointeurs (6) Tableau et pointeur : arithmétique des pointeurs tab[i] <=> *(tab+i) Le compilateur connaît le type des éléments du tableau → il fait des sauts de N octets en N octets (selon le type des éléments du tableau) void init(int t[], int n) { int i; for(i=0;i<n;i++) t[i] = 3*i; } int main() { int tab[3]; init(tab,3); return 0; void init(int *t, int n) { int i; for(i=0;i<n;i++) *(t+i) = 3*i; } int main() { int tab[3]; init(tab,3); return 0; <=>
Tableaux et pointeurs (7) Recopie de tableaux ? int t1[2],t2[2]; t1 = t2; → Interdit (erreur : incompatible types...) Mais … int t1[2],*t2; t2 = t1; → OK Attention : Vous n'avez pas recopié le tableau … seulement le pointeur ! → Les deux « tableaux » pointent sur les mêmes cases (ils contiennent la même adresse). t1[1] = 3; t2[1] = 0; CINI_print_int(t1[1]); → Affiche 0
Déclaration et initialisation de pointeurs Soit : int a =12, b ; char c; float ff = 12.3; Quelles sont les déclarations correctes ? Corrigez. int * aa = a ; int * ab = &a; int * ac = *ab; char * ca = &ff; char * cb = &c; float* fa = ab; float fb = &ff; &fa = 29.7;
Fonctions et pointeurs Soit la fonction main suivante : int main(){ int num = 739, unit, diz, cent; /* appel de la fonction decompose */ CINI_print_string("decomposition de "); CINI_print_int(num); CINI_print_string("centaine : "); CINI_print_int(cent); CINI_print_string("dizaine : "); CINI_print_int(diz); CINI_print_string("unite : "); CINI_print_int(unit); return 0; } Définissez la fonction decompose et écrivez l'instruction d'appel de cette fonction.
Fonctions et pointeurs Soit g une fonction dont la signature est la suivante : float g(float *x, float y); L’appel suivant de la fonction g est il correct ? Justifiez par rapport à tous les types en cause. float t[] = {1,2}; float d = g(t,1.0); Même question avec l'appel suivant : int u[] = {1,2}; u[1] = g(u+1,u[0]);
Tableaux et fonctions Qu'affiche le code suivant ? Pourquoi ? #include <cini.h> void f2(int tab[], int taille){ int i; for (i=0;i<taille;i++) if (tab[i]%2 == 0) tab[i] = tab[i]/2; } int main(){ int tabf[5] = {1,2,6,3,7}; for (i=0;i<5;i++) CINI_print_int(tabf[i]); CINI_newline(); f2(tabf,5); return 0;
Pointeurs et passage par référence Écrivez une fonction compte qui ne retourne rien et qui prend en paramètres un tableau de caractères tab, sa taille taille et un caractère c. La fonction doit permettre de récupérer le nombre d'apparitions du caractère dans le tableau.
Arithmétique des pointeurs Qu'affiche le programme suivant ? #include <cini.h> int main(){ char * tabC = "bonjour"; CINI_print_char(*tabC); CINI_newline(); CINI_print_char(*(tabC+3)); tabC = tabC + 2; return 0; }