I have this simple structure I want to initialize on the heap and return as a pointer in a function.
struct entry {
const char* const key; // We don't want the key modified in any way
const void* data; // But the pointer to data can change
struct entry* next;
};
There is one problem, I cannot calloc
it and initialize members one by one because key
is a const pointer. I found somewhere this syntax that works:
struct entry* entry = calloc(1, sizeof(struct entry));
*entry = (struct entry) { .key = key, .data = data, .next = NULL };
But I don't know what is going on with it: does it create an "anonymous" struct that is then copied to the place where *entry
lives? Is that safe to use or should I prefer creating a local struct that is then copied with memcpy
to the right location?
The assignment you presented is not correct and should not compile.
The correct way of initializing an allocated struct with const members is to allocate some memory, create a temporary struct entry object, and then use memcpy to copy the object to the allocated memory:
This line:
uses the assignment operator. The conditions for assignment operator (C11 6.5.16/2) include:
The definition of modifiable lvalue can be found in 6.3.2.1/1:
So
*entry
is not a modifiable lvalue, because its type is a struct that has a member with const-qualified type. Therefore it is a constraint violation to have*entry
appear on the left-hand-side of the assignment operator.The clang compiler (all versions I tried) appears to not give any diagnostic message for this constraint violation; this is clearly a compiler bug. gcc does give a diagnostic.
Regarding the second part of the question:
As also explained by 2501, you can do this in C when writing into space allocated by the
malloc
family. (If you had declared a namedstruct entry
object then it is less clear whethermemcpy
ing over it is permitted).