====== Fonctions ====== ===== Exemple simple ===== #include #include int plus(int a, int b){ return a + b; } int main() { int y = 4; int x = plus(y, 18); printf("%d\n", x); return 0; } == ligne 4, signature == En ligne 4, on a défini une fonction ''%%plus%%'' //c'est la signature de la fonction//. * La signature commence par ''%%int%%'' ce qui signifie que cette fonction doit renvoyer un ''%%int%%'' * Il faut toujours indiquer le type de retour. * Si une fonction ne renvoie rien, il faut préciser ''%%void%%''. * On précise également les arguments de la fonctions, ''%%a%%'' et ''%%b%%'' et là encore, on doit préciser leur type. * Le début et la fin de la fonction sont délimités par ''%%{...}%%'' * Comme d'habitude avec les fonctions, on ne connaît pas les valeurs de ''%%a%%'' et ''%%b%%''. On sait seulement que ce seront des entiers. Les valeurs seront connues au moment de l'exécution de la fonction. == ligne 5, retour == Puisque la fonction a un retour de type ''%%int%%'', il est indispensable qu'elle renvoie un entier. Ici, elle renvoie la somme de ''%%a%%'' et ''%%b%%'' ce qui sera bien un entier. == ligne 10, appel de la fonction == La fonction ''%%plus%%'' est appelée avec les arguments : * ''%%y%%'' qui est bien un entier, vaut 4 et prend la place de l'argument ''%%a%%'' de la fonction. Dans l'exécution, ''%%a%%'' vaudra donc 4. * ''%%18%%'' qui prend la place de l'argument ''%%b%%''. * L'exécution de la fonction renvoie donc ''%%22%%''. * Le retour de la fonction est écrit dans la variable ''%%x%%'', de type entier également. * L'affichage de ''%%x%%'' en ligne 7 confirme que ''%%x%%'' a pris la valeur 22. **Important :** Pour permettre son exécution ligne 10, la fonction doit-être définie avant. > Il est possible de ne définir que la signature de la fonction et de ne donner le contenu que plus tard. ===== Les arguments ne sont pas modifiés ===== Prenons cet autre exemple : #include #include int add(int a, int b){ a = a + b; return a; } int main() { int a = 5; int x = plus(a, 18); printf("%d\n", x); printf("%d\n", a); return 0; } == Des variables différentes == Ligne 4 et ligne 10, on définit ''%%int a%%''. Elles ont beau porter le même nom, ce sont deux variables différentes. L'affectaton ligne 13 ''%%a = a + b;%%'' n'a pas d'effet sur la variable ''%%a%%'' définie ligne 10. Pour éviter les confusions, il est peut-être utile de changer de nom. On peut le faire ici dans le cadre de cette explication, mais c'est on ne peut pas toujours le faire : Dans un gros programme on a inévitablement des variables différentes portant le même nom. Le mécanisme dont on parle maintenant permet justement qu'elles vivent sans se perturber l'une l'autre. #include #include int add(int c, int b){ c = c + b; return a; } int main() { int a = 5; int x = plus(a, 18); printf("%d\n", x); printf("%d\n", a); return 0; } == Création d'une copie == Au moment de l'appel ligne 11 : ''%%int x = plus(a, 18);%%'', on lance la fonction définie ligne 4 par ''%%int add(int c, int b){%%''. Cela signifie qu'à son lancement, la fonction ''%%add%%'' initialise une nouvelle variable ''%%c%%'' dans laquelle il recopie la valeur qu'on lui fournit, ici le contenu de ''%%a%%''. Donc ''%%c%%'' est initialisé comme copie de ''%%a%%''. Quand on modifie ''%%c%%'' en ligne 5, cela n'a donc pas d'effet sur ''%%a%%''. ===== Portée - scope ===== Quand on définit une variable, elle a une certaine portée. La portée est définie par les fonctions. Dans le cas précédent, ''%%c%%'' n'existe que le temps de l'exécution de la fonction ''%%plus%%''. Un appelle à la variable ''%%c%%'' en dehors de la fonction ''%%plus%%'' provoque une erreur. Dès que la fonction se termine, l'espace mémoire alloué à ''%%c%%'' est libéré. La variable n'existe plus. C'est vrai aussi des variables définies dans ''%%main%%'' : ''%%a%%'' et ''%%x%%'' sont définies dans ''%%main%%'' et sont inaccessibles depuis ''%%plus%%''. Le seul moyen de les mettre en relation est d'utiliser les entrées - sorties de la fonction : En mettant ''%%a%%'' comme argument de ''%%plus%%'', ''%%plus%%'' va travailler sur une copie de la valeur de ''%%a%%''. À l'autre bout, ''%%x%%'' reçoit le résultat de l'exécution de ''%%plus%%''. C'est la seule interaction possible. > On verra que l'on peut aller plus loin avec les [[.:pointeurs|pointeurs]] mais ce principe général reste valable. ===== Variable globale ===== Si une variable est définie en dehors des fonctions, elle peut être atteinte de façon globale. Voyons un exemple : #include #include int a = 25; void change_a(){ a = a + 1; } int main() { printf("%d\n",a); change_a(); printf("%d\n",a); return 0; } La variable ''%%a%%'' définie ligne 4 a une portée globale. Lors de l'exécution de ''%%change_a%%'', en ligne 7, c'est bien ce ''%%a%%'' global qui est modifié et dans les affichages lignes 11 et 13, c'est toujours le même ''%%a%%''. ===== Modifier un argument ===== Supposons que l'on veuille modifier un argument (c'est souvent utile, par exemple : ''%%tri(tableau)%%'', il peut être utile que ''%%tri%%'' modifie le contenu de ''%%tableau%%''. == Avec pointeurs == La méthode consiste à ne pas transmettre la variable elle-même comme argument mais l'adresse de la variable de façon à ce que la fonction agisse directement sur la case mémoire contenant la variable. Cela correspond aux [[.:pointeurs|pointeurs]]. #include #include void change(int *a){ *a = *a + 1; } int main() { int x = 13; printf("%d\n",x); change(&x); printf("%d\n",x); return 0; } * ligne 4, ''%%a%%'' est défini comme étant ''%%int *%%'', c'est à dire un pointeur sur un entier. ''%%a%%'' est une adresse désignant une case contenant un entier. ''%%*a%%'' désigne le contenu de la case, donc un entier. D'ailleurs on le comprend puisque on note ''%%int *a%%'' ce qui veut bien dire que ''%%*a%%'' est un ''%%int%%''. * le calcul ligne 5 porte sur ''%%*a%%'', donc le contenu de la case mémoire pointée par ''%%a%%''. * ligne 10, on appelle la fonction en transmettant ''%%&x%%'', c'est à dire l'adresse de la variable ''%%x%%''. Donc, au lancement de ''%%change%%'' c'est l'adresse de ''%%x%%'' qui est copiée dans ''%%a%%''. Le pointeur ''%%a%%'' pointe la case mémoire de ''%%x%%''. ''%%*a%%'' désigne donc le contenu de ''%%x%%'' et les modifications portées à ''%%*a%%'' affectent le contenu de ''%%x%%''. == La version C++ == En C++ on peut utiliser ''%%&%%'' qui est appelé dans ce cas //ampersed// (utile à savoir si vous devez faire une recherche !) > Cette méthode fonctionne sur [[https://cplayground.com/|C playground]] puisque le compilateur utilisé sur ce site est un compilateur C++. #include #include void change(int &a){ a = a + 1; } int main() { int x = 13; printf("%d\n",x); change(x); printf("%d\n",x); return 0; } En ligne 4, dans la définition de ''%%change%%'', l'argument ''%%a%%'' est précédé de ''%%&%%''. Ce symbole indique que la variable est passée **par référence**. Je vais expliciter le mot ci-dessous. Voyons l'exécution pour bien comprendre : * ligne 11, on appelle ''%%change(x)%%''. ''%%x%%'' à la place de l'argument ''%%a%%''. Mais ''%%a%%'' ne va pas être un nouvel entier recopiant la valeur de ''%%x%%''. ''%%a%%'' sera en fait ''%%x%%'' lui même, c'est cela que signifie **par référence**. * ligne 12, contrairement au mécanisme normal, la modification de ''%%a%%'' entraîne la modification de de ''%%x%%'' car l'utilisation de ''%%&%%'' fait que ce sont les mêmes variables..