سؤال

I didn't find an exact answer to this question so either it's a stupid question or just plain obvious. I would like to know if it would produce undefined behaviour.

I have some struct type defined:

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

I need multiple instances of that struct (like you'd have in struct array), but the number of objects is unknown at compile time.

Is it correct to initialize it like this?

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() part is what I'm worried about.

هل كانت مفيدة؟

المحلول 2

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

Yes, it's safe, in the sense that this won't cause any undefined behaviour (buffer overflows, uninitialised values, etc.).

However, it won't necessarily set your values to zero. memset sets the bits to 0, but this isn't necessarily the same as setting e.g. a float to a value of 0 (although in practice, it will be fine on most normal platforms).

نصائح أخرى

Using malloc followed by memset is OK so far as it goes, but you might wish to consider the (under-used) calloc instead. For example:

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

This will allocate memory for the required number of elements, and initialise them to binary zero.

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

You're right to be worried - your memset simply sets all bits to zero which doesn't necessarily set members to 0.

For instance, nothing guarantees all-bits-0 will actually mean 0 for a float. The same holds for a pointer: making it all-bits-0 does not mean it will necessarily be NULL.


EDIT

NULL may or may not be represented as all-bits-0. Quoting the C FAQ:

The internal (or run-time) representation of a null pointer, which may or may not be all-bits-0 and which may be different for different pointer types.

The memset in your code will set all the bits to 0 which may or may not be what you want to do. In particular, it's not guaranteed that a pointer with all zero bits is the null pointer. Nor that a floating value with all zero bits is zero.

If you want your code to be completely portable then you should initialise 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 could do the initialization with a C99 compound literal:

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

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

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top