What is special about structs?

I know that in C we cannot return an array from a function, but a pointer to an array. But I want to know what is the special thing about structs that makes them return-able by functions even though they may contain arrays.

Why is the struct wrapping makes the following program valid?

#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;
}
4612 次浏览

First of all, to quote C11, chapter §6.8.6.4, return statement, (emphasis mine)

If a return statement with an expression is executed, the value of the expression is returned to the caller as the value of the function call expression.

Returning a structure variable is possible (and correct), because, the structure value is returned. This is similar to returning any primitive data type (returning int, for example).

On the other hand, if you return an array, by using the return <array_name>, it essentially returns the address of the first element of the arrayNOTE, which becomes invalid in the caller if the array was local to the called functions. So, returning array in that way is not possible.

So, TL;DR, there is nothing special with structs, the speciality is in arrays.


NOTE:

Quoting C11 again, chapter §6.3.2.1, (my emphasis)

Except when it is the operand of the sizeof operator, the _Alignof operator, or the unary & operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue. [...]

A better way of asking the same question would be "what is special about arrays", for it is the arrays that have special handling attached to them, not structs.

The behavior of passing and returning arrays by pointer traces back to the original implementation of C. Arrays "decay" to pointers, causing a good deal of confusion, especially among people new to the language. Structs, on the other hand, behave just like built-in types, such as ints, doubles, etc. This includes any arrays embedded in the struct, except for flexible array members, which are not copied.

There isn't anything special about struct types; it's that there's something special about array types that prevents them from being returned from a function directly.

A struct expression is treated like an expression of any other non-array type; it evaluates to the value of the struct. So you can do things like

struct foo { ... };


struct foo func( void )
{
struct foo someFoo;
...
return someFoo;
}

The expression someFoo evaluates to the value of the struct foo object; the contents of the object are returned from the function (even if those contents contain arrays).

An array expression is treated differently; if it's not the operand of the sizeof or unary & operators, or if it isn't a string literal being used to initialize another array in a declaration, the expression is converted ("decays") from type "array of T" to "pointer to T", and the value of the expression is the address of the first element.

So you cannot return an array by value from a function, because any reference to an array expression is automatically converted to a pointer value.

Structs have data members public by default so it is possible in case of struct to access data in main but not in case of class. So , the struct wrapping is valid.