Initializing an array of C structure with a size not known at compile time

I did not find the exact answer to this question, so either this is a stupid question, or simply obvious. I would like to know if this will produce undefined behavior.

I have a specific type of structure:

typedef struct { char string1[17]; char string2[33]; int someInt; float someFloat; } my_struct_t; 

I need several instances of this structure (for example, in your struct array), but the number of objects is unknown at compile time.

Is it right to initialize?

 my_struct_t *myStruct; size_t noOfElements; size_t completeSize; int index; /* ...code which sets the number of elements at runtime... */ completeSize = sizeof(my_struct_t) * noOfElements; myStruct = malloc(completeSize); memset(myStruct, 0, completeSize); /* ...and then access it as if it were an array...*/ myStruct[index].someInt = 10; // index < noOfElements 

Is it safe to do this? The memset() is what I'm worried about.

+7
source share
4 answers

Is it safe to do this? The memset () part is what I'm worried about.

Yes, it is safe, in the sense that it will not cause undefined behavior (buffer overflow, uninitialized values, etc.).

However, this does not necessarily lead to zero of your values. memset sets the bit to 0, but this does not necessarily match the setting, for example. a float to a value of 0 (although in practice this will be normal on most conventional platforms).

+9
source

Using malloc followed by a memset is as good as possible, but you can use a (underused) calloc instead. For example:

 pMyStruct = calloc(noOfElements, sizeof(my_struct_t)); 

This will allocate memory for the required number of elements and initialize them with binary zero.

+10
source

Is it safe to do this? The memset () part is what I'm worried about.

You are right to worry - your memset just sets all bits to zero, which does not necessarily set members to 0.

For example, nothing guarantees that all-bits-0 actually means 0 for float. The same is true for a pointer: what makes it bit-0 does not mean that it will necessarily be NULL .


EDIT

NULL may or may not be represented as all bit-0. Quoting C Frequently Asked Questions:

An internal (or temporary) representation of a null pointer, which may or may not be bits-0, and which may differ for different types of pointers.

+4
source

memset in your code will set all bits to 0, which may or may not be what you want to do. In particular, this does not guarantee that a pointer with all zero bits is a null pointer. In addition, the floating value with all zero bits is zero.

If you want your code to be fully portable, you must initialize each element.

 my_struct_t *arr = malloc(N * sizeof arr[0]); const my_struct_t default_my_struct = { 0 }; for (int i=0; i<N; i++) arr[i] = default_my_struct; 

Or you can initialize with the C99 literal:

 my_struct_t *arr = malloc(N * sizeof arr[0]); for (int i=0; i<N; i++) arr[i] = (my_struct_t) { 0 }; 

In practice, you will have to work hard to find a C implementation for which the above code will have a different result from your version that uses memset .

+1
source

All Articles