Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where are arrays in structs Allocated?

Tags:

c

malloc

struct

Let's say I have the following struct.

struct Vector3{
    double Values[3];
};

I know I can do something like:

struct Vector3 v1;
v1.Values[0] = -1;
printf("%f", vi.Values[0]);

And it will work just fine. I didn't have to malloc/calloc the .Values. Compiling with -c99 -Wall gives me no warnings. But I have a questions about such struct.

In this case, where v1 is a local variable:

  • The 'doubles' of .Values are allocated on the stack or the heap?
  • If they are allocated on the heap, is this code guaranteed to always work? Or is it compiler-dependent?

If have this other struct

struct Triplet{
    double First;
    double Second;
    double Third;
};

Could I "memcpy" the contents of a Vector3 to a Triplet?

Last but not least, what about this struct? Same rules as Vector3?

struct Matrix3{
    double Values[3][3];
};
like image 448
Trauer Avatar asked Nov 27 '25 14:11

Trauer


2 Answers

Where are arrays in structs Allocated

The same place the struct itself is allocated, either on the stack or the heap depending on how you instantiate the struct.

struct Vector3 v1;

Allocates all memory needed for Vector3 on the stack.

Could I "memcpy" the contents of a Vector3 to a Triplet?

That depends on how the struct is packed on your target platform and based on your compiler settings and possibly #pragma affecting packing. There is no general guarantee that you can just memcopy the data. It will work on some platforms and can then fail on other platforms.

like image 70
Eric J. Avatar answered Nov 30 '25 03:11

Eric J.


1) The 'doubles' of .Values are allocated on the stack or the heap?

They are part of your struct, that's what "member" means. So they're allocated wherever your struct is allocated.

Could I "memcpy" the contents of a Vector3 to a Triplet?

In general: no. For example, arrays are contiguous, structs can contain unused padding between their members. It comes down to your triplet struct is not a compatible type to your vector3 struct.

edit: anatolyg's comment to this question gives me an idea about how someone could come up with it, indeed, it's probably because arrays and pointers often "look" similar (and some very bad resources even claim they were the same).

They are not!

An array really is just a sequence of variables of the same type, this is even true for multi-dimensional arrays. The stored object is nothing else than the total number of elements declared (read: the values) in a row.

For a pointer, the stored object is an address.

What's often confusing is two things:

  1. an array can't be passed to a function. When you do so, it's implicitly converted to a pointer (the function gets a pointer to the array).
  2. Probably for ease of use, the index operator ([]) works on a pointer, too.

What happens internally with indexing ([]) is different. For an array, it just denotes the indexed element of that array.(*) For a pointer, it is assumed the pointer actually points to an array, so the pointer is incremented by the given index before dereferencing (thus accessing the indexed element of the array pointed to).

Example:

int a[5];
int *p;

now a[3] just accesses the 4th element of a. But p[3] is actually equivalent to *(p+3).

(*) In fact, *(a+3) would be a valid expression, too, and according to the C standard, it is equivalent to a[3] because [] is defined in terms of pointer arithmetics. It works because an array is always implicitly converted to a pointer when used as one. Don't let this confuse you, it still isn't a pointer


Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!