user311413 user311413 - 2 months ago 8
C Question

How does memory allocation of non-homogeneous array work?

Using a

union
, we can certainly have an array containing elements of different data types.

e.g.

struct elements {
int s;
union {
int ival;
float fval;
char *pval;
} element;
};
struct darray {
struct elements items[100];
};


Now, we can declare an array which can contain elements of different data types:

struct darray a;


What is troubling me: Only a single member of a union can exist at a single time, but we have already got an array containing 100 elements. These elements aren't initialized, but shouldn't memory be allocated here?

How does memory allocation works in such arrays?

Answer

Let's look on the following piece of code:

#include <stdio.h>
#include <stdlib.h>

typedef union __attribute__((__packed__)) {
    int   ival;
    int   fval;
    char* pval;
} element;

typedef struct __attribute__((__packed__)) { 
    int     s;
    element e;
} elements;

typedef struct __attribute__((__packed__)) {
    elements items[100];
} darray;

int main()
{
    darray d = {0};
    printf("size of element: %lu.\n", sizeof(element));
    printf("size of elements: %lu.\n", sizeof(elements));
    printf("size of darray: %lu.\n", sizeof(darray));
    return 0;
}
// The output is:
//  size of element: 8
//  size of elements: 12
//  size of elements: 1200

Now let's explain what has just happened:

  1. I'm using 64-bit machine so pointers are of size 8.
  2. We used __attribute__((__packed__)) in order to force the compiler not padding our structs with extra bytes of memory. It's like telling him, use the minimum amount of memory you need to build a struct which contains the following members.
  3. Notice that although it's unknown what element is carrying right now, it already has size in compile time. The size of element is 8, Why? union size is fixed by its larger member (here we have int, which is 4, float which is 4, and char* which is 8 [64-bit machine again...]).
  4. Now that we know that union has a fixed size, creating array of 100 members, will require memory of 100 * sizeof(elements) = 100 * (sizeof(int) + sizeof(element)) = 100 * (4 + 8) = 1200 bytes.