for (i=0;i< nb_tableau;i++) {
 t[i] = malloc(sizeof(**t) * lignes); 
 /* deuxième dimension */
 if (t[i]==NULL) { 
 printf ("Impossible d'initialiser avec malloc\n" ); 
 exit (-1); 
 for (j=0;j<lignes;j++) {
 /* troisième dimension */
 t[i][j] = malloc(sizeof(***t) * colonnes); 
 if (t[i][j]==NULL) 
 printf ("Impossible d'initialiser avec malloc\n" ); 
 exit (-1); 
 return t;
Utilisation des pointeurs sur des tableaux particuliers.
Il est possible avec un pointeur de lire/parcourir les éléments d'une structure.
Chaque éléments d'une structure utilise un espace qui permet de calculer des déplacements.
Cependant cette utilisation est dangereuse, comme dans l'exemple ci-dessous qui ne fonctionne que sur les processeurs où la taille d'un pointeur égale celle d'un entier de type codice_1, ce qui n'est généralement pas le cas sur les processeurs 64 bits.
struct s
 int a;
 int b;
 char *s;
}s;
int main(void)
 struct s st={1,1,"salut"};
 void *p=&st;
 printf("%s\n", (char *)((void **)p)[2]);
 /* <!> si sizeof(int) < sizeof(void*) le pointeur pointe après la structure ! */
 /*<==OU==>*/
 p += 2*sizeof(int);
 printf("%s\n", (char *)((void **)p)[0]);
 p -= 2*sizeof(int);
 memset(p,-1, 2*sizeof(int));
 printf("%i,%i\n", st.a, st.b);
 memset((int *)p,0, 2*sizeof(int));
 printf("%i,%i\n", st.a, st.b);
 ((int *)p)[0] = 1;
 ((int *)p)[1] = 0;
 printf("%i,%i\n", st.a, st.b);
 printf("%s\n", st.s);
 return 0;
Utilisation des pointeurs pour passer des paramètres par adresse.
Toutes les variables en C, à l'exception des tableaux, sont passés par valeurs aux paramètres des fonctions. C'est à dire qu'une copie est effectuée sur la pile d'appel. Si bien que toutes les modifications de la variable effectuées dans la fonction seront perdues une fois de retour à l'appelant. Or, il y a des cas où l'on aimerait bien pouvoir modifier une variable passée en paramètre et que ces modifications perdurent dans la fonction appelante. C'est un des usages des paramètres par adresse : permettre la modification d'une variable de l'appelant, comme dans l'exemple suivant :
/* Ce code échange le contenu de deux variables */
void echange(int *a, int *b)
 int tmp = *a;
 *a = *b;
 *b = tmp;
int main(void)
 int a = 5;
 int b = 2;
 printf("a = %d, b = %d.\n", a, b);
 /* On passe à 'echange' les adresses de a et b. */
 echange(&a, &b);
 printf("a = %d, b = %d.\n", a, b);
 echange(&a, &b);
 printf("a = %d, b = %d.\n", a, b);
 return 0;
Ce passage par adresse est extrêmement répandu pour optimiser la quantité de données qui doit transiter sur la pile d'appel (qui est, sur beaucoup de systèmes, de taille fixe). En fait, même si la variable ne doit pas être modifiée, on utilise quand même un passage par adresse, juste pour éviter la copie implicite des variables autres que les tableaux. Ceci est particulièrement intéressant avec les structures, puisque celles-ci ont tendance à être assez imposantes, et cela ne nuit pas trop la lisibilité du programme.
Tableaux dynamiques et passage de tableaux comme arguments d'une fonction.
Comme on vient de le voir, l'intérêt principal d'une allocation dynamique est de pouvoir lancer son programme sans connaître la taille du tableau qu'on utilisera; celle-ci sera établie en cours de fonctionnement.
Cependant, un autre intérêt du tableau dynamique est de pouvoir être passé comme argument d'une fonction pour des tableaux à plusieurs dimensions.
En reprenant la fonction codice_37 vue précédemment, on peut écrire :
int fonction_3d (int ***tab);
int main(int argc, char **argv)
 /* Tableau dynamique créé avec des malloc() */
 int ***tab = malloc_3d(2, 10, 10);
 fonction_3d (tab);
 return EXIT_SUCCESS;
/* fonction recevant le tableau en 3d */
void fonction_3d (int ***tab)
 /* On peut utiliser ici la notation tab[i][j][k] en veillant à 
 ce que i, j, k ne sortent pas des bornes du tableau -> dans 
 cet exemple tab[3][9][9] est illégal alors que tab[1][3][7] 
 peut être utilisé.
 On ne pourra pas savoir si on sort du tableau !
Pointeurs vers fonctions.
Les pointeurs vers les fonctions sont un peu spéciaux, parce qu'ils n'ont pas d'arithmétique associée (car une telle arithmétique n'aurait pas beaucoup de sens). Les opérations permises avec les pointeurs sur fonctions sont en fait relativement limitées :
type_retour (*pointeur_fonction)(liste_paramètres);
Déclare codice_38, un pointeur vers une fonction prenant codice_39 comme paramètres et renvoyant codice_40. Le parenthésage est ici obligatoire, sans quoi l'étoile se rattacherait au type de retour. Pour faire pointer un pointeur vers une fonction, on utilise une affectation « normale » :
pointeur_fonction = &fonction;
/* Qui est en fait équivalent à : */
pointeur_fonction = fonction;
Où codice_41 est compatible avec le pointeur (mêmes paramètres et valeur de retour). Une fois que le pointeur pointe vers une fonction, on peut appeler cette fonction :
(*pointeur_fonction)(paramètres);
/* Ou plus simplement, mais moins logique syntaxiquement */
pointeur_fonction(paramètres);
Exemple simple d'utilisation de pointeur de fonction avec retour.
On fait une comparaison de deux entiers (5 et 4) via un pointeur sur une fonction de comparaison.
int comparaison_plus_grand_que(int a, int b) 
 return a > b ; 
int main(int argc, char * argv[])
 int taille = 10;
 int (*p_comparaison)(int,int); // pointeur de fonction
 int a = 5, b = 4;
 p_comparaison = comparaison_plus_grand_que;
 if((*p_comparaison)(a,b)) // appel de la fonction via le pointeur
 printf("%d est plus grand que %d\n", a ,b);
 else
 printf("%d est plus petit que %d\n", a ,b);
 return EXIT_SUCCESS;
Pointeurs de fonctions.
Exemple numérique.
Code source.
/* ------ Fonction f ------------ */
char feq[] = "x**2";
/* ------ Fonction g ------------ */
char geq[] = "2.0*x + 3.0";
/* -Fonction fog (g suivie de f)-*/
double f1_o_f2(
double (*P_f1)(double x),/* Pointeur pour la première fonction */
double (*P_f2)(double x),/* Pointeur pour la deuxième fonction */
double a
 return((*P_f1)( ((*P_f2)(a))) );
/* ------------------------------ */
/* ------------------------------ */
int main(void)
double a = 2.0;
 printf(" f : x-> %s\n", feq);
 printf(" g : x-> %s\n", geq);
 printf(" \n\n");
 printf(" f(g(%.0f)) = %6.1f\n", a, f1_o_f2(f,g,a));
 printf(" g(f(%.0f)) = %6.1f\n", a, f1_o_f2(g,f,a));
 printf(" f(f(%.0f)) = %6.1f\n", a, f1_o_f2(f,f,a));
 printf("\n\n Press return to continue.\n");
 getchar();
 return 0;
Résultat ;
 f : x-> x**2
 g : x-> 2.0*x + 3.0
 f(g(2)) = 49.0
 g(f(2)) = 11.0
 f(f(2)) = 16.0
 Press return to continue.
Exemple graphique (avec Gnuplot).
Code source.
/* --- Dessinons f et g --------- */
/* Le fichier de points: [a,f(a)] */
void Gplt(
double (*P_f)(double x)
FILE *fp;
double a;
 fp = fopen("data","w");
 for(a = -5.0; a <= 5.0; a += 0.3)
 fprintf(fp," %6.3f %6.3f\n",
 a, ((*P_f)(a)) );
 fclose(fp);
int main(void)
 printf("f) Dans gnuplot -> plot \"data\" ");
 Gplt(f);
 getchar();
 printf("g) Dans gnuplot -> plot \"data\" ");
 Gplt(g);
 printf("\n\n Press return to continue.\n");
 getchar();
 return 0;
Tableau de pointeurs de fonctions.
Premier exemple.
Nous avons des fonctions semblables. Nous voulons les associer pour pouvoir les manipuler dans des boucles. 
Nous allons créer un tableau de pointeurs de fonctions.
Je vais utiliser les fonctions trigonométriques prédéfinies pour faciliter la lecture.
Déclaration d'un tableau de pointeurs de fonctions.
double (*TrigF[6])(double x) = {cos,sin,tan,atan,asin,acos};
Exemple d'un appel.
 cos(.5) = TrigF[0](.5)
Exemple à tester.
int main(void)
double (*TrigF[6])(double x) = {cos,sin,tan,atan,asin,acos};
double x= .5;
int i= 0;
 printf(" Nous avons declare un tableau "\
 " de pointeurs de fonctions.\n "\
 " J'ai utilise ici les fonctions predefinie du c.\n");
 printf(" cos(%.1f) = %.3f \n", x, cos(x));
 printf(" TrigF[%d](%.1f)) = %.3f\n\n",i,x,TrigF[i](x));
 printf(" Press return to continue");
 getchar();
 return 0;
Résultat dans un fichier.
int main(void)
FILE *fp = fopen("list.txt","w");
double (*TrigF[6])(double x) = {atan,asin,acos,tan,cos,sin};
int i= 6; 
double x= .1;
fprintf(fp," x || sin cos tan acos asin atan \n");
 for(;x<=.5;x+=.1)
 fprintf(fp," %.1f ||",x);
 for(i=6;i;)
 fprintf(fp," %.3f ",TrigF[--i](x));
 fprintf(fp,"\n");
 fclose(fp);
 printf("\n\n Ouvrir le fichier list.txt\n");
 getchar();
 return 0;
Le résultat :
 x || sin cos tan acos asin atan 
 0.1 || 0.100 0.995 0.100 1.471 0.100 0.100 
 0.2 || 0.199 0.980 0.203 1.369 0.201 0.197 
 0.3 || 0.296 0.955 0.309 1.266 0.305 0.291 
 0.4 || 0.389 0.921 0.423 1.159 0.412 0.381 
 0.5 || 0.479 0.878 0.546 1.047 0.524 0.464 
Remarque : 
Au démarrage :
Au final :
Avec résultat à l'écran.
/* ------------------------------ */
int main(void)
double (*TrigF[6])(double x) = {atan,asin,acos,tan,cos,sin};
int i= 6;
double x= .1;
 for(;x<=.5;x+=.1)
 printf("\n");
 for(i=6;i;) printf(" %.3f ",TrigF[--i](x));
 printf("\n\n Press return to continue.\n");
 getchar();
 return 0;
Deuxième exemple.
Nous voulons créer la fonction Derivate capable de calculer la dérivé première et seconde d'une fonction, en utilisant un tableau de pointeurs de fonctions.
Déclaration d'un tableau de pointeurs de fonctions.
double (*Derivate[3])(double (*P_f)(double x),double a,double h) = {fx,Dx_1,Dx_2};
Exemple d'un appel.
 f(x)=Derivate[0](f,x,0.)
Exemple à tester.
/* ------ Fonction f ------------ */
char feq[] = "x**2";
/* ------ Fonction g ------------ */
double g(double x){return(
char geq[] = "cos(x)**2+sin(x)+x-3";
double fx(
double (*P_f)(double x),
double a,
double h
 return( ((*P_f)(a)) );
 f'(a) = f(a+h) - f(a-h)
 2h
double Dx_1(
double (*P_f)(double x),
double a,
double h
 return( ( ((*P_f)(a+h))-((*P_f)(a-h)) ) / (2.*h) );
 f"(a) = f(a+h) - 2 f(a) + f(a-h)
 h**2
double Dx_2(
double (*P_f)(double x),
double a,
double h
 return( (((*P_f)(a+h))-2*((*P_f)(a))+((*P_f)(a-h))) / (h*h) );
int main(void)
double (*Derivate[3])(double (*P_f)(double x),
 double a,
 double h) = {fx,Dx_1,Dx_2};
double x = 2;
double h = 0.001;
printf("\n\n");
printf(" f(%.3f) = %.3f = %.3f \n",x,f(x), Derivate[0](f,x,0.));
printf(" f'(%.3f) = %.3f = %.3f \n",x,Dx_1(f,x,h),Derivate[1](f,x,h));
printf("f"(%.3f) = %.3f = %.3f \n",x,Dx_2(f,x,h),Derivate[2](f,x,h));
printf("\n\n");
printf(" g(%.3f) = %.3f = %.3f \n",x,g(x), Derivate[0](g,x,0.));
printf(" g'(%.3f) = %.3f = %.3f \n",x,Dx_1(g,x,h),Derivate[1](g,x,h));
printf("g"(%.3f) = %.3f = %.3f \n",x,Dx_2(g,x,h),Derivate[2](g,x,h));
 printf("\n\n Press return to continue.");
 getchar();
 return 0;