Considering that the type A
is defined like this:
typedef struct a { const int a; } A;
I know that this code is valid:
A * foo = malloc(sizeof *foo); // Allocates uninitialized memory with no effective type
memcpy(foo, &(typeof(*foo)){ .a = 42, }, sizeof *foo); // Effectively initialize the value once
(see https://stackoverflow.com/a/79012045/13242312)
But is it still valid with alloca
instead of malloc
if we want the value to be on the stack instead of the heap ?
Use case: I want a single return path in my function, so I want to define the result variable at the function scope
A A_new(void) {
A * a = alloca(sizeof *a);
if (/* something */) {
memcpy(a, &(typeof(*a)){.a = 1}, sizeof *a);
} else {
memcpy(a, &(typeof(*a)){.a = 2}, sizeof *a);
}
return *a;
}
Whether alloca
or malloc
is used has no effect on the relevant semantics, except that alloca
is not a standard C library function.
You can avoid semantic questions about const
by not using the destination type while preparing the memory. For example:
A A_new(void)
{
typedef typeof (A_new()) T; // Define type T for brevity.
void *p = alloca(sizeof (T));
if (!p) HandleError();
// Memory is copied as bytes; the type T has not yet been applied to it.
if (something)
memcpy(p, & (T) { . a = 1 }, sizeof (T));
else
memcpy(p, & (T) { . a = 2 }, sizeof (T));
// Return an object of type T.
return * (T *) p;
}
The accessing of memory as type T
in the return
statement is defined by the C standard because the memory has been given effective type T
by copying into it the bytes of a T
object, so it is accessed with its effective type.
Your sample code does not illustrate any need to use dynamic allocation, from either malloc
or alloca
. The entire function body could be just:
return (typeof (A_new())) { .a = something ? 1 : 2 };
I realize the sample code may be overly simplified, so that perhaps more than just .a = something ? 1 : 2
is needed in the original code. However, the dynamic allocation could still be avoided by recording the member values in their own objects or a parallel structure without const
members, such as:
A A_new(void)
{
struct { int a; } Temporary;
if (something)
Temporary.a = 1;
else
Temporary.a = 2;
return (typeof (A_new()) { .a = Temporary.a };
}