0

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?

6
  • 3
    Well, pCoords[0] to pCoords[user_size - 1], but yes. It doesn't have to impose any structure on the allocated memory; it just has to know the size of each item. Commented May 16, 2015 at 13:16
  • 3
    p.s. Don't cast the result of malloc() Commented May 16, 2015 at 13:16
  • @Paul: thank you for Array bounds Commented May 16, 2015 at 14:09
  • If I omit the cast, Visual Studio throws error C2440 at me (cannot convert from 'void *' to 'PCOORDS'). Commented May 16, 2015 at 14:16
  • 1
    I suppose that's because VS automatically creates projects with source files already ending on .cpp - so I get strict C++ type checking, right? Commented May 16, 2015 at 14:30

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.