Je sais qu'en C, nous ne pouvons pas retourner un tableau à partir d'une fonction, mais un pointeur vers un tableau. Mais je veux savoir quelle est la particularité de structs
qui les rend renvoyables par les fonctions même si elles peuvent contenir des tableaux.
Pourquoi l'habillage struct
rend le programme suivant valide?
#include <stdio.h>
struct data {
char buf[256];
};
struct data Foo(const char *buf);
int main(void)
{
struct data obj;
obj = Foo("This is a sentence.");
printf("%s\n", obj.buf);
return 0;
}
struct data Foo(const char *buf)
{
struct data X;
strcpy(X.buf, buf);
return X;
}
Une meilleure façon de poser la même question serait "ce qui est spécial à propos des tableaux", car ce sont les tableaux qui ont un traitement spécial qui leur est attaché, pas struct
s.
Le comportement de passage et de retour de tableaux par pointeur remonte à l'implémentation d'origine de C. Arrays "decay" aux pointeurs, provoquant beaucoup de confusion, en particulier chez les personnes nouvelles dans le langage. Les structures, en revanche, se comportent exactement comme les types intégrés, tels que int
s, double
s, etc. Cela inclut tous les tableaux intégrés dans le struct
, à l'exception de - membres du tableau flexible , qui ne sont pas copiés.
Tout d'abord, pour citer C11
, chapitre §6.8.6.4, return
instruction, ( accentuation mine )
Si une instruction
return
avec une expression est exécutée, la la valeur de l'expression est renvoyée à l'appelant comme valeur de l'expression d'appel de fonction.
Le retour d'une variable de structure est possible (et correct), car la valeur de la structure est retournée. Cela revient à renvoyer n'importe quel type de données primitif (renvoyant int
, par exemple).
En revanche, si vous renvoyez un tableau , en utilisant le return <array_name>
, il retourne essentiellement l'adresse du premier élément du tableauREMARQUE, qui devient invalide dans l'appelant si le tableau était local aux fonctions appelées. Ainsi, le retour de tableau de cette manière n'est pas possible.
Donc, TL; DR, il n'y a rien spécial avec struct
s, la spécialité est dans tableaux .
REMARQUE:
Citant C11
encore une fois, chapitre §6.3.2.1, ( mon accent )
Sauf lorsqu'il s'agit de l'opérande de l'opérateur
sizeof
, le_Alignof
, ou l'unaire&
, ou est un littéral de chaîne utilisé pour initialiser un tableau, ne expression de type '' tableau de type '' est converti en une expression avec type '' pointeur vers type '' qui pointe vers l'élément initial de l'objet tablea et n'est pas une valeur l. [...]
Il n'y a rien de spécial dans les types struct
; c'est qu'il y a quelque chose de spécial dans les types array qui les empêche d'être renvoyés directement d'une fonction.
Une expression struct
est traitée comme une expression de tout autre type non tableau; il évalue à valeur du struct
. Vous pouvez donc faire des choses comme
struct foo { ... };
struct foo func( void )
{
struct foo someFoo;
...
return someFoo;
}
L'expression someFoo
correspond à la valeur de la struct foo
objet; le contenu de l'objet est renvoyé par la fonction (même si ce contenu contient des tableaux).
Une expression de tableau est traitée différemment; si ce n'est pas l'opérande de sizeof
ou unaire &
opérateurs, ou s'il ne s'agit pas d'un littéral de chaîne utilisé pour initialiser un autre tableau dans une déclaration, l'expression est convertie ("decays") de type "tableau de T
" en "pointeur vers T
", et la valeur de l'expression est l'adresse du premier élément.
Vous ne pouvez donc pas retourner un tableau par valeur à partir d'une fonction, car toute référence à une expression de tableau est automatiquement convertie en valeur de pointeur.