Puis-je renvoyer le pointeur sur VLA?

Un tel prototype de fonction est-il valide en C?

int (*func())[*]; 

Et si c’est le cas, comment puis-je définir de telles fonctions?

À partir de la norme C (6.2.1 Portée des identificateurs)

  1. … (Un prototype de fonction est une déclaration d’une fonction qui déclare les types de ses parameters .)

et (6.7.6.2 Déclarateurs de tableau)

  1. … Si la taille est * au lieu d’être une expression, le type de tableau est un type de tableau de longueur variable de taille non spécifiée, qui ne peut être utilisé que dans des déclarations ou des noms de type avec une scope de prototype de fonction ;

Vous ne pouvez donc pas spécifier le type de retour de la fonction de la manière que vous avez indiquée.

Tenez compte du fait que 1) les fonctions peuvent ne pas avoir de types de retour de tableaux et 2) les tableaux de longueur variable ont une durée de stockage automatique. Ainsi, si un tel tableau pouvait être renvoyé, la fonction avait un comportement indéfini. Voir 6.7.6.2 Déclarateurs de tableau:

2 Si un identificateur est déclaré comme ayant un type modifié de manière variable, il doit s’agir d’un identificateur ordinaire (tel que défini au 6.2.3), ne pas avoir de liaison et avoir une scope de bloc ou une scope de prototype de fonction. Si un identificateur est déclaré être un object ayant une durée de stockage statique ou de thread, il ne doit pas avoir de type tableau de longueur variable.

Je connais deux approches à votre problème. Soit allouer un tableau dynamicment et renvoyer un pointeur à son premier élément. Ou emballez un tableau dans une structure. Dans ce cas, vous pouvez renvoyer la structure entière d’une fonction sous forme de valeur rvalue.

Vous devez plutôt renvoyer un pointeur sur un type de tableau incomplet, car la notation * pour les tableaux de longueur variable n’est valide que dans les listes de parameters.

Exemple de prototype et définition de fonction:

 extern float (*first_row(unsigned, unsigned, float (*)[*][*]))[]; float (*first_row(unsigned n, unsigned m, float (*masortingx)[n][m]))[] { return *masortingx; } 

Vous l’invoqueriez comme ceci:

 unsigned n = 3, m = 4; float masortingx[n][m]; float (*row)[m] = first_row(n, m, &masortingx); 

Notez que le fait de renvoyer un pointeur sur un tableau (de longueur variable ou autre) déclaré dans la fonction si sa durée de stockage automatique est un comportement indéfini. Cela implique que vous pouvez uniquement renvoyer un pointeur sur un tableau de longueur variable que vous avez transmis sous forme d’argument ou alloué de manière dynamic.

Techniquement, vous le pouvez, mais ce n’est pas une bonne idée.

 int * func(size_t s) { int array[s]; return array; } 

Après avoir été défini, un tableau de longueur variable n’est pas différent d’un tableau classique. Il se décompose donc en un pointeur lorsque vous essayez de le renvoyer. Le renvoi d’un pointeur sur une variable locale entraîne un comportement indéfini.