Loading lang_c_04_pointers...
double // nouvelle position x après intégration de la vitesse v pendant dt integrate(double x, double v, double dt) { x+=v*dt; // x du contexte local est modifié, pas x0 du contexte appelant if(x<0.0) { x=0.0; } return x; // une copie de la valeur de x est renvoyée vers le contexte appelant }
... dans une autre fonction ... { double x0=... , v0=... , dt=... ; // trois valeurs quelconques double x1=integrate(x0, v0, dt); // x0 conserve sa valeur, x1 obtient la nouvelle position ... }
void integrate(double *inout_x, // deux passages par adresse, c'est-à-dire par pointeur double *inout_v, double a, // deux passages par valeur double dt) { double x=*inout_x, v=*inout_v; // acquisition de ce qui est désigné par les pointeurs x+=(v+0.5*a*dt)*dt; // calculs sur des variables locales v+=a*dt; if(x<0.0) { x=0.0; } *inout_x=x; // altération de ce qui est désigné par les pointeurs *inout_v=v; }
... dans une autre fonction ... { double x0=... , v0=... , a=... , dt=... ; // quatre valeurs quelconques integrate(&x0, &v0, a, dt); // x0 et v0 peuvent être modifiées par cet appel, a et dt non ... }
... { int *v1; // un pointeur sur entier de valeur indéterminée double v2, *v3; // un réel et un pointeur sur réel de valeurs indéterminées int *v4=(int *)0, v5=8, *v6=&v5; // un entier et deux pointeurs sur entier initialisés int *v7=v6, *v8, *v9=NULL; // deux pointeurs initialisées, un autre indéterminé ... }
<stddef.h>).
... { double x1=... , x2=... ; // deux valeurs quelconques double *p=x1<x2 ? &x1 : &x2 ; // désigner la plus petite *p+=1.5; // modifier la plus petite *p*=*p; // ... ... }
... { double x1=... , x2=... ; // deux valeurs quelconques if(x1<x2) { x1+=1.5; // si x1 a la valeur minimale x1*=x1; // nous la modifions } else { x2+=1.5; // si x2 a la valeur minimale x2*=x2; // nous la modifions } ... }
double * chooseBest(double *p1, double *p2, double *p3, double *p4) { if(*p1<*p2) { return *p1<*p3 ? (*p1<*p4 ? p1 : p4) : (*p3<*p4 ? p3 : p4); } else { return *p2<*p3 ? (*p2<*p4 ? p2 : p4) : (*p3<*p4 ? p3 : p4); } }
... dans une autre fonction ... { double x1=... , x2=... , x3=... , x4=... ; // quatre valeurs quelconques double *p=chooseBest(&x1, &x2, &x3, &x4); // désigner la variable correspondant au critère *p+=1.5; // modifier la variable choisie *p*=*p; ... }
int * definitelyIncorrectFunction(int i) // !!! NE JAMAIS ÉCRIRE UN FONCTION COMME CELLE-CI !!! { int twice=i+i; return &twice; // l'adresse renvoyée désigne une variable qui va immédiatement disparaître ! }
... dans une autre fonction ... { int *v1=definitelyIncorrectFunction(7); // l'adresse obtenue peut désigner n'importe quoi ! int v2=*v1; // la valeur obtenue est indéterminée ! ... }
... { double values[5]; // values est un tableau de cinq réels dont la valeur est indéterminée for(int i=0; i<5; ++i) // les élément sont numérotés à partir de zéro { values[i]=3.5*i+0.5; // désormais chacun des cinq réels a une valeur } for(int i=1; i<5; ++i) // nous nous interdisons d'accéder à un élément inexistant { values[i]+=values[i-1]; // consultation et modification des réels du tableau } printf("%g\n",values[4]); // 37.5 ... }
... { int v1[5]; // cinq valeurs indéterminées int v2[5]={2, 3, 5, 7, 11}; // cinq valeurs explicitement spécifiées int v3[3]={i, 4*i+3, f(i)}; // trois valeurs calculées à l'exécution int v4[]={10, 20, 30, 40}; // les quatre éléments dimensionnent et initialisent le tableaux int v5[20]={2, 3, 5, 7, 11}; // cinq valeurs spécifiées, les quinze autres à zéro int v6[200]={0}; // deux cents valeurs à zéro ... }
{et , et
}matérialisent cette construction.
... { int v1[3]={10, 20, 30}; // correct : trois valeurs explicitement spécifiées int v2[3]; // correct : trois valeurs indéterminées
// v2={40, 50, 60}; // incorrect : pas d'affectation pour un tableau ! v2[0]=40; // correct : affectation des éléments v2[1]=50; v2[2]=60; for(int i=0; i<3; ++i) { v2[i]=10*(i+4); // correct : affectation des éléments }
// v2=v1; // incorrect : pas d'affectation pour un tableau ! for(int i=0; i<3; ++i) { v2[i]=v1[i]; // correct : affectation des éléments } ... }
... { double values[]={1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9}; printf("size of double: %d\n", (int)sizeof(double)); // 8 (dépend de la plateforme) printf("size of element: %d\n", (int)sizeof(values[0])); // 8 (taille d'un double) printf("size of array: %d\n", (int)sizeof(values)); // 72 (taille de neuf éléments) int elementCount=(int)(sizeof(values)/sizeof(values[0])); printf("element count: %d\n", elementCount); // 9 (nombre d'éléments dans le tableau) for(int i=0; i<elementCount; ++i) { printf("%g ", values[i]); // 1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 9.9 } ... }
... { double values1[8] ={ 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8}; // disposition aplatie double values2[2][4]={{1.1, 2.2, 3.3, 4.4}, {5.5, 6.6, 7.7, 8.8}}; // deux lignes, quatre colonnes int row=1, column=2; printf("%g %g\n", values1[4*row+column], values2[row][column]); // 7.7 7.7 ... }
... { double values[4]={1.1, 2.2, 3.3, 4.4}; double *p=values; // conversion implicite de double[] vers double * (équivaut à p=&values[0]) printf("%g\n", *p); // 1.1 (le pointeur désigne bien le premier élément du tableau) *p=9.9; // modification de la donnée désignée par le pointeur p=&values[2]; // désignation d'un élément au choix dans le tableau *p=8.8; // modification de la nouvelle donnée désignée par le pointeur for(int i=0; i<4; ++i) { printf("%g ", values[i]); // 9.9 2.2 8.8 4.4 (les éléments du tableau ont bien été modifiés) } printf("\n"); ... }
... { double values[4]={1.1, 2.2, 3.3, 4.4}; double *p=values; // conversion implicite de double[] vers double * (équivaut à p=&values[0]) for(int i=0; i<4; ++i) { p[i]+=2.0; // accès indexé à des éléments désignés par le pointeur } for(int i=0; i<4; ++i) { printf("%g ", values[i]); // 3.1 4.2 5.3 6.4 (les éléments du tableau ont bien été modifiés) } printf("\n"); ... }
int // indice de l'élément choisi chooseBest(double *p, int count) { int best=0; for(int i=1; i<count; ++i) { if(p[i]<p[best]) { best=i; } } return best; }
... dans une autre fonction ... { double values[100]={ ... }; // cent valeurs quelconques int best=chooseBest(values, 100); // désigner l'élément correspondant au critère values[best]+=1.5; // modifier l'élément choisi values[best]*=values[best]; best=chooseBest(&values[20], 60); // même chose sur les éléments d'indice 20 à 79 values[best]+=1.5; // ... values[best]*=values[best]; ... }
void f1(double *p1); // void f2(double p2[]); // ces trois prototypes sont strictement équivalents ! void f3(double p3[10]); //
... { double values[5]={ ... }; f1(values); // f2(values); // ces trois appels sont corrects f3(values); // ... }
... { printf(" char: %d, *: %d\n", (int)sizeof(char), (int)sizeof(char *) ); // char: 1, *: 8 printf(" int: %d, *: %d\n", (int)sizeof(int), (int)sizeof(int *) ); // int: 4, *: 8 printf("double: %d, *: %d\n", (int)sizeof(double), (int)sizeof(double *)); // double: 8, *: 8 ... }
... { double values[10]={0.0, 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9}; double *p=values+3; // pointeur de début de tableau avancé de trois éléments printf("%g\n", *p); // 3.3 (le pointeur désigne bien values[3]) ++p; // passage à l'élément suivant, *p+=40.04; // puis modification de la donnée pointée p=values+9; // désignation du dernier élément du tableau printf("%g\n", *p); // 9.9 (le pointeur désigne bien values[9]) p-=2; // recul de deux éléments, *p+=70.07; // puis modification de la donnée pointée for(int i=0; i<10; ++i) { printf("%g ", values[i]); // 0.0 1.1 2.2 3.3 44.44 5.5 6.6 77.77 8.8 9.9 } printf("\n"); ... }
... { double *p= ... ; // adresse d'un élément dans un tableau suffisamment grand int i= ... ; // un indice convenable vis-à-vis de p et de son tableau d'origine if(( p[i] == *(p+i) )&& // les expressions de part ( p[0] == *p )&& // et d'autre de ces égalités ( &p[i] == p+i )) // sont strictement équivalentes { printf("this is always true!\n"); } ... }
... { double values[10]={0.0, 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9}; double *p1=values+2, *p2=values+8; printf("%d %d\n", (int)(p1-values), (int)(p2-values)); // 2 8 printf("%d %d\n", (int)(p1-p2), (int)(p2-p1)); // -6 6 ... }
<stddef.h>) à ce type est ptrdiff_t.
double arraySum_A(double *begin, double *end) { double sum=0.0; for(double *p=begin; p<end; ++p) { sum+=*p; // utilise l'arithmétique des pointeurs } return sum; }
double arraySum_B(double *p, int count) { double sum=0.0; for(int i=0; i<count; ++i) { sum+=p[i]; // utilise l'indexation } return sum; }
... dans une autre fonction ... { double values[100]={ ... }; // cent valeurs quelconques double sum_A=arraySum_A(values, values+100); // deux pointeurs double sum_B=arraySum_B(values, 100); // un pointeur et un entier if(sum_A==sum_B) { printf("this is always true!\n"); } ... }
void showPointer(int *ptr) { if(ptr) // équivalent à if(ptr!=(int *)0) ou encore if(ptr!=NULL) { printf("it points to the value %d\n", *ptr); } else { printf("it points nowhere!"); } }
... { double d=12.34, *p1=&d; int *p2=(int *)p1; // conversion extrêmement risquée (cela n'a probablement aucun sens) printf("%g %d\n", *p1, *p2); // 12.34 2061584302 (une valeur entière possible) ... }
void showArray(const double *p, int count) { for(int i=0; i<count; ++i) { printf("%g ", p[i]); // consultation des valeurs pointées } // *p+=10.0; // incorrect : modification d'une valeur pointée interdite // double *p2=p; // incorrect : perte du qualificatif const interdite }
... dans une autre fonction ... { double values[100]={ ... }; // cent valeurs quelconques const double *p=values+20; // ajout implicite du qualificatif const autorisé showArray(p, 60); showArray(values, 100); // ajout implicite du qualificatif const autorisé ... }
... { double values[4]={1.1, 2.2, 3.3, 4.4}; double *p1=values+1; printf("%g\n", *p1); // 2.2 double **p2=&p1; // p2 désigne p1 *p2+=2; // modifier *p2 revient à modifier p1 printf("%g %g\n", *p1, **p2); // 4.4 4.4 (déréférencement de p1, double-déréférencement de p2) ... }