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); }