user2286339
user2286339

Reputation: 194

c malloc array of struct

So far, I have dealt a bit with pointers and structs, but I'm not sure how to allocate an array of a structure at runtime - see below.

N.B. "user_size" is initialized at runtime.

typedef struct _COORDS
{
    double x;
    double y;
    double area;
    double circumference;
    int index;
    wchar_t name[16];
} COORDS, *PCOORDS;

PCOORDS pCoords = (PCOORDS)malloc(sizeof(COORDS)* user_size);
// NULL ptr check omitted 

After that, can I just access pCoords[0] to pCoords[user_size-1] as with an ordinary array of ints?

More to the point: I don't understand how the compiler superimposes the layout of the structure on the alloc'ed memory? Does it even have to or am I overthinking this?

Upvotes: 0

Views: 436

Answers (2)

Jongware
Jongware

Reputation: 22478

The compiler does not super-impose the structure on the memory -- you tell it to do so!

An array of structures is accessed by multiplying the index of one element by its total size. pCoords[3], for example, is "at" pCoords + 3*sizeof(COORDS) in memory.

A structure member is accessed by its offset (which is calculated by the sizes of the elements before it, taking padding into account). So member x is at an offset 0 from the start of its container, pCoords plus sizeof(COORDS) times the array element index; and y is sizeof(x) after that.

Since you tell the compiler that (1) you want a contiguous block of memory with a size for user_size times the size of a single COORD, and (2) then access this through pCoords[2].y, all it has to do is multiply and add, and then read the value (literally) in that memory address. Since the type of y is double, it reads and interprets the raw bytes as a double. And usually, it gets it right.

The only problem that can arise is when you have multiple pointers to that same area of memory. That could mean that the raw bytes "at" an address may need interpreting as different types (for instance, when one pointer tells it to expect an int and another a double).

With the provisio that the valid range is acutally 0..user_size - 1, your code is fine.

Upvotes: 1

derhass
derhass

Reputation: 45362

You are probably overthinking this. The compiler does not "superimpose" anything on the malloc'ed memory - that is just a bunch of bytes.

However, pointers are typed in C, and the type of the pointer determines how the memory is interpreted when the pointer is derefenced or used in pointer artihmetic. The compiler knows the memory layout of the struct. Each field has a defined size and an offset, and the overall size of the struct is known, too.

In your case, the expression pCoords[i].area = 42.0 is equivalent to

char *pByte = (char*)pCoords + sizeof(COORDS) * i + offsetof(COORDS, area);
double *pDouble = (pDouble*)pByte;
*pDouble = 42.0;

Upvotes: 1

Related Questions