Return a `struct` from a function in C
As far as I can remember, the first versions of C only allowed to return a value that could fit into a processor register, which means that you could only return a pointer to a struct. The same restriction applied to function arguments.
More recent versions allow to pass around larger data objects like structs. I think this feature was already common during the eighties or early nineties.
Arrays, however, can still be passed and returned only as pointers.
You can return a structure from a function (or use the =
operator) without any problems. It's a well-defined part of the language. The only problem with struct b = a
is that you didn't provide a complete type. struct MyObj b = a
will work just fine. You can pass structures to functions as well - a structure is exactly the same as any built-in type for purposes of parameter passing, return values, and assignment.
Here's a simple demonstration program that does all three - passes a structure as a parameter, returns a structure from a function, and uses structures in assignment statements:
#include <stdio.h>
struct a {
int i;
};
struct a f(struct a x)
{
struct a r = x;
return r;
}
int main(void)
{
struct a x = { 12 };
struct a y = f(x);
printf("%d\n", y.i);
return 0;
}
The next example is pretty much exactly the same, but uses the built-in int
type for demonstration purposes. The two programs have the same behaviour with respect to pass-by-value for parameter passing, assignment, etc.:
#include <stdio.h>
int f(int x)
{
int r = x;
return r;
}
int main(void)
{
int x = 12;
int y = f(x);
printf("%d\n", y);
return 0;
}
When making a call such as a = foo();
, the compiler might push the address of the result structure on the stack and passes it as a "hidden" pointer to the foo()
function. Effectively, it could become something like:
void foo(MyObj *r) {
struct MyObj a;
// ...
*r = a;
}
foo(&a);
However, the exact implementation of this is dependent on the compiler and/or platform. As Carl Norum notes, if the structure is small enough, it might even be passed back completely in a register.
The struct b
line doesn't work because it's a syntax error. If you expand it out to include the type it will work just fine
struct MyObj b = a; // Runs fine
What C is doing here is essentially a memcpy
from the source struct to the destination. This is true for both assignment and return of struct
values (and really every other value in C)