Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Initializing a C struct array, with a size not known at compile time

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.

like image 702
Tomislav Avatar asked Dec 31 '12 12:12

Tomislav


3 Answers

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.

like image 110
cdarke Avatar answered Nov 16 '22 16:11

cdarke


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).

like image 24
Oliver Charlesworth Avatar answered Nov 16 '22 15:11

Oliver Charlesworth


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.

like image 4
cnicutar Avatar answered Nov 16 '22 15:11

cnicutar