Reputation: 27385
GCC compiles function returning a struct with a flexible array member fine. The Standard gives a definition on how it treats such structs at 6.7.2.1:
In most situations, the flexible array member is ignored. In particular, the size of the structure is as if the flexible array member were omitted except that it may have more trailing padding than the omission would imply.
Since the size of the struct with flexible array member is known the type is complete according to the completeness definition given at 6.2.5:
At various points within a translation unit an object type may be incomplete (lacking sufficient information to determine the size of objects of that type) or complete (having sufficient information). 37)
Also, 6.5.2.2
The expression that denotes the called function 96) shall have type pointer to function returning void or returning a complete object type other than an array type.
So it should be legal to return struct
s with flexible array members.
How to fix an example below to make it work properly (I need stack allocated struct with flexible array member):
#include <stdio.h>
struct test{
size_t sz;
char data[];
};
struct test get_test(void){
int sz = 5;
char data[5] = "test";
struct test test = {.sz = 5};
//How to copy char data[5] into the struct test test?
return test;
}
int main(void){
struct test tst = get_test();
printf("%s\n", tst.data);
}
Upvotes: 2
Views: 816
Reputation: 133919
Yes it is valid C to return such a value, but none of the array elements will be copied. The automatic variable will behave as if it did allocate with an array of length 1 (because array length of 0 is not valid in standard C), but accesses to .data[0]
will have UB - the actual size of the object might include the .data[0]
and perhaps even more successive elements - or then not.(C11 6.7.2.1p18).
It is not possible to define an automatic variable that would have any content in the flexible array member in standard C (extensions may and do exist)!
An assignment is valid too (and hence returning too), but again the flexible array member will contain indeterminate values (C11 6.7.2.1p25) after assignment.
Upvotes: 5
Reputation: 84561
How to fix an example below to make it work properly (I need stack allocated struct with flexible array member):
A Flexible Array Member allows for a single dynamic allocation of both the struct and FAM. (you can't have a stack allocated struct and dynamic FAM -- if you want to do that, don't use a FAM, use a pointer for data
instead.) To allocate and utilize the FAM, you need to change your function to return a pointer to type struct test
(e.g. struct test*
) and then declare and allocate storage for both your struct and storage for "test"
in get_test
and return a pointer to the allocated block, e.g.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct test {
size_t sz;
char data[];
};
struct test *get_test (void) /* declare as type struct test* */
{
size_t sz = 5;
char data[] = "test";
/* allocate storage for struct + FAM */
struct test *test = malloc (sizeof *test + sizeof data);
if (!test)
return NULL;
test->sz = sz; /* assign sz */
memcpy (test->data, data, sizeof data); /* copy data */
return test;
}
int main (void) {
struct test *tst = get_test();
printf ("test->sz : %zu\ntest->data : %s\n", tst->sz, tst->data);
free (tst); /* don't forget to free what you allocate */
}
Example Use/Output
$ ./bin/fam
test->sz : 5
test->data : test
Upvotes: 4