问题
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?
回答1:
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:
void* mem = malloc( sizeof( struct entry ) );
struct entry temp = { key , data , NULL };
memcpy( mem , &temp , sizeof( temp ) );
struct entry* e = mem;
回答2:
This line:
*entry = (struct entry) { .key = key, .data = data, .next = NULL };
uses the assignment operator. The conditions for assignment operator (C11 6.5.16/2) include:
Constraints
An assignment operator shall have a modifiable lvalue as its left operand.
The definition of modifiable lvalue can be found in 6.3.2.1/1:
A modifiable lvalue is an lvalue that does not have array type, does not have an incomplete type, does not have a const-qualified type, and if it is a structure or union, does not have any member (including, recursively, any member or element of all contained aggregates or unions) with a const-qualified type.
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:
should I prefer creating a local struct that is then copied with memcpy to the right location?
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 named struct entry
object then it is less clear whether memcpy
ing over it is permitted).
来源:https://stackoverflow.com/questions/36751204/use-of-struct-initialization-syntax-for-on-heap-struct