Dans les langages de programmation il existe deux techniques de passage d'arguments :
Le langage C a choisi la 2 solution.
Si un argument doit être passé par adresse, c'est le programmeur qui en prend l'initiative et ceci grâce à l'opérateur d'adressage (&).
Exemple
#include <stdio.h> void main() { int a, b, c; void somme(int a, int b, int *c); a = 3; b = 8; somme(a, b, c); printf("Somme de a et b : %d\n", c); return; } void somme(int a, int b, int *c) { *c = a + b; return; }
Il convient d'être prudent lors de l'utilisation d'une fonction retournant un pointeur. Il faudra éviter l'erreur qui consiste à retourner l'adresse d'une variable temporaire.
Exemple
#include <stdio.h> void main() { char *p; char *ini_car(void); p = ini_car(); printf("%c\n", *p); } char *ini_car(void) { char c; c = '#'; return(c); <=== ERREUR }
Un vecteur est une constante symbolique dont la valeur est l'adresse
de son 1 élément.
Lorsqu'un vecteur est passé en argument, c'est donc l'adresse de son
1 élément qui est transmise par valeur.
Exemple
#define NbElements(t) sizeof t / sizeof t[0] #include <stdio.h> main() { int tab[] = { 1, 9, 10, 14, 18}; int somme(int t[], int n); void impression(int *t, int n); printf("%d\n", somme(tab, NbElements(tab))); impression(tab, NbElements(tab)); } int somme(int t[], int n) { int i, som=0; for (i=0; i < n; i++) som += t[i]; return som; } void impression(int *t, int n) { int i=0, *p; for (p=t; t-p < n; t++) printf("t[%d] = %d\n", i++, *t); }
Exemple
#define NbElements(t) sizeof t / sizeof t[0] #include <stdio.h> main() { int tab[][5] = { { 4, 7, 1, 9, 6}, { 5, 9, 3, 4, 2}, { 2, 9, 5, 9, 13} }; int somme(int (*t)[5], int n); printf("Somme des elements de tab : %d\n", somme(tab, NbElements(tab))); } int somme(int (*t)[5], int n) { int i, som = 0; int (*p)[5] = t; for(; t-p < n; t++) for (i=0; i < 5; i++) som += (*t)[i]; return som; }
Exemple
#define DIM1 10 #define DIM2 4 #define DIM3 5 main() { int tab[DIM1][DIM2][DIM3]; void init(int (*t)[DIM3], int n); int i, n = DIM2; for(i=0; i i < DIM1; i++) init(tab[i], i); } void init(int (*t)[DIM3], int n) { int i, j; for(i=0; i < DIM2; i++) for(j=0; j < DIM3; j++) { t[i][j] = 2*(i+n*DIM2); *(*(t+i)+j) += 1; } }
La norme ANSI a introduit la possibilité de transmettre une structure en argument d'une fonction, elle-même pouvant retourner un tel objet.
Exemple
#include <stdio.h> #define NbElts(v) ( sizeof v / sizeof v[0] ) typedef struct { float v[6]; } Vecteur; main() { Vecteur v = { {1.34f, 8.78f, 10.f, 4.f, 22.12f, 3.145f} }; Vecteur inv; Vecteur inverse(Vecteur v, int n); int i, n = NbElts(v.v); inv = inverse(v, n); for (i=0; i < n; i++) printf("inv.v[%d] : %f\n", i, inv.v[i]); } Vecteur inverse(Vecteur v, int n) { Vecteur w; int i; for(i=0; i < n; i++) w.v[i] = v.v[i] ? 1./v.v[i] : 0.f; return w; }
Le nom d'une fonction est une constante symbolique dont la valeur
est un pointeur sur la 1 instruction exécutable du code machine
de la fonction. Passer une fonction en argument, c'est donc transmettre
l'adresse, par valeur, du début du code machine constituant cette
fonction.
Exemple
double integrale(double b_inf, double b_sup, int pas, double (*f)(double)); double carre(double x); void main() { double b_inf, b_sup, aire; int pas; b_inf = 1., b_sup = 6., pas = 2000; aire = integrale(b_inf, b_sup, pas, carre); printf("Aire : %f\n", aire); } double integrale(double b_inf, double b_sup, int pas, double (*f)(double)) { double surface = 0., h; int i; h = (b_sup - b_inf)/pas; for(i=0; i< pas; i++) surface += h*(*f)(b_inf+i*h); return surface; } double carre(double x) {return x*x;}
Lorsqu'un exécutable est lancé sous un interprète de commandes ({shell}), un processus est créé et son exécution commence par la fonction main à laquelle des arguments sont transmis après avoir été générés par le shell.
Ces arguments sont constitués de :
Par convention :
Exemple
La commande a.out toto titi tata génère la structure de données suivante :
Tableau des arguments
Exemple
#include <stdio.h> main(int argc, char **argv, char **envp) { void usage(char *s); if (argc != 3) usage(argv[0]); for(; *argv; argv++) printf("%s\n", *argv); for(; *envp; envp++) printf("%s\n", *envp); } void usage(char *s) { fprintf(stderr, "usage : %s arg1 arg2\n", s); exit(1); }