web-dev-qa-db-fra.com

Quelle est la particularité des structures?

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;
}
81
user5619103

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 structs.

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 ints, doubles, 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.

100
dasblinkenlight

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 structs, 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. [...]

38
Sourav Ghosh

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.

11
John Bode