Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Questions sur les déclarateurs de fonctions

12 réponses
Avatar
Taurre
Bonjour =E0 tous,

Je m'excuse d'avance pour le titre un peu flou, mais j'avoue ne pas
avoir trouv=E9 mieux.
Je viens vers vous car j'ai deux questions en rapport avec les
"d=E9clarateurs" de fonctions, plus pr=E9cis=E9mment au sujet des param=E8t=
res
de type tableaux:

- j'ai lu qu'il =E9tait possible d'indiquer qu'une fonction recevait un
tableau de longueur variable comme ceci:

void fonction(int tab[*]);

Cependant, je ne comprend pas l'int=E9r=EAt de cette =E9criture qui est
limit=E9e aux prototypes de fonctions (6.7.5.3 =A7 12 p 119). En effet,
dans le cas o=F9 je passes un tableau de longueur variable en argument
d'une fonction, ce dernier est implicitement converti en un pointeur
sur son premier =E9l=E9ment (6.3.2.1 =A7 3 p 46). J'aurais donc tr=E8s bien=
pu
me contenter de sp=E9cifier tab comme de type "pointeur sur int". D=E8s
lors, o=F9 est l'int=E9r=EAt de l'=E9criture ci-dessus?

- j'ai =E9galement vu qu'il =E9tait possible d'utiliser le mot-cl=E9 static
juste avant la taille d'un param=E8tre de type tableau, par exemple
comme ceci:

void fonction(int tab[static 10]);

=C0 ce sujet, la Norme nous dit (6.7.5.3 =A7 7 p 119):

> If the keyword static also appears within the [ and ] of the
> array type derivation, then for each call to the function, the value of t=
he corresponding
> actual argument shall provide access to the first element of an array wit=
h at least as many
> elements as specified by the size expression.

Je comprends cette phrase comme une obligation pour le tableau fourni
en argument d'avoir une taille minimale. Cependant, je constate que
violer cette interdiction n'entra=EEne aucune erreur/avertissement du
c=F4t=E9 de GCC (4.4.5). D=E8s lors, de nouveau, quel est l'int=E9r=EAt de =
cette
=E9criture si elle est purement indicative puisque dans ce cas, indiquer
la taille sans le mot-cl=E9 static suffit?

Merci d'avance pour vos r=E9ponses.

2 réponses

1 2
Avatar
Antoine Leca
Taurre écrivit :
Maintenant, pour reprendre l'exemple de static, c'est son intérêt que
je ne comprends pas...



C'est pour permettre des optimisations opportunistes de la part de
certains compilateurs à la recherche de performances.

Beaucoup de fonctionnalités C99 sont inspirées de Fortran, car à la fin
des années 1990 le principal reproche qui était adressé aux vendeurs de
compilateurs C et qui ne pouvait pas être couvert par les compilateurs
C++ ou Java, était le manque de performances face aux compilateurs
Fortran (je parle bien évidemment ici des compilateurs commerciaux).


En effet, si le but est purement indicatif,



Euh, non, ce n'est pas purement indicatif : si tu passes un tableau de
10 caractères ou un pointeur nul comme argument d'une fonction définie:

int f(char tab[static 1048576], size_t n)
{
if( !tab ) return -1; // test inutile / « stupide » en C99

char local[1048576];
memcpy(local, tab, n<1048576 ? n : sizeof local);
// un compilo C99 peut passer outre le n<1048576?
// et copier systématiquement 1048576 bytes...
// (par exemple par copie de page si cela l'intéresse)
//...

Et tu ne peux pas te plaindre si le processeur te sort par SIGSEGV...
Contrairement à (char tab[]), la notation avec static « garantit » en
effet au compilateur que la valeur passée est bien un pointeur vers un
tableau d'au moins X éléments, par conséquent n'est pas un pointeur nul.

Évidemment, ce genre d'optimisations n'est pas forcément indispensable;
en fait (et là je préviens la réponse de Marc ;-) ) il est même des
contextes où elles seraient plutôt néfastes...


Antoine
Avatar
Taurre
Voilà qui répond tout à fait à mes questions :)
Merci beaucoup pour vos réponses ;)
1 2