4

When we declare say :

int array[2];

array = " Holds the address of the first 32 bits" i.e it holds &array[0]. So the "array" is a pointer. But when we declare a struct for example:

typedef struct x 
{
    int y;
    int array[2];
}

Why the size of this struct is 16 bytes ? shouldn't it be 8 bytes since "array" is a pointer ? I am so confused ?

7
  • 6
    An array is not a pointer, though it may decay into one in some cases, but here the entire array is stored in the struct. The most likely scenario is that you're compiling for x64 and sizeof(int) == 4, so you have 12 meaningful bytes and 4 bytes of padding, which gives a total of 16 bytes. Commented Nov 17, 2015 at 20:35
  • 1
    array is actually an array here and not just a pointer. That means that the size of 2 elements is actually allocated inside each and every instance of the x struct. Commented Nov 17, 2015 at 20:36
  • sizeof(struct x) should be 12 not 16 . and is defined as {int,{int,int}}; Commented Nov 17, 2015 at 21:00
  • 1
    @milevyo (Arbitrary) padding is permitted. Commented Nov 17, 2015 at 21:01
  • 1
    @milevyo, arbitrary padding is permitted. C does not specify how much padding may or should be used. In practice, a C compiler for a 64-bit machine might well prefer to pad structures to a multiple of 64 bits (8 bytes) so as to be able to align them on 64-bit boundaries. In that case, if int is 4 bytes then the given structure would need to be padded to a total of 16. Commented Nov 17, 2015 at 21:36

4 Answers 4

3

First up array here is an array with space allocated within the struct to contain all the elements of that array. It's not a pointer to space outside the struct. With regards to how much space everything takes up the easiest way to see what's going on here is just to run some sizeof checks here:

#include <stdio.h>
typedef struct x 
{
    int y;
    int array[2];
};

int main(void) {
    struct x test1;
    printf("sizeof(int) %zu \n", sizeof(int));
    printf("sizeof(test1) %zu \n", sizeof(test1));
    printf("sizeof(test1.array) %zu", sizeof(test1.array));
    return 0;
}

When run on ideone you get the 4, 12 and 8 here. http://ideone.com/pKBe1X On other systems I've run this I get similar results which leads me to believe that on your machine with your particular compiler options some padding has been added to your structs.

If sizeof(test1.y) + sizeof(test1.array) != sizeof(test1) then you have some padding added in. Adding something such as #pragma pack (ms compiler) or __attribute__((__packed__)) (gcc) will likely change this.

The reason padding would be added by your compiler is because on your particular system there is likely some benefit in terms of access to data speed from having data structures with this particular alignment (multiples of 16 bytes) in memory. For more on that I'd recommend having a look at the Wikipedia page on data structure alignment.

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

Comments

2

When we declare say :

int array[2];

array = " Holds the address of the first 32 bits" i.e it holds &array[0].

Nope. Not at all. When you declare a 2-element array, what you get is something like the following:

     +---+
arr: |   | arr[0]
     +---+ 
     |   | arr[1]
     +---+

The object associated with the identifier arr is a 2-element array of int, not a pointer. Under most circumstances, the expression arr will be converted ("decay") to an expression of type "pointer to int".

An instance of your struct type would look like:

       +---+
    y: |   | 
       +---+
array: |   | array[0]
       +---+
       |   | array[1]
       +---+

The sum of the sizes of the members is only 12 bytes, so there must be some padding after array to meet an 8- or 16-byte alignment restriction.

Comments

1

An array has some characteristics of a pointer, but it is not a pointer itself. Namely, you can't make it point somewhere else. It always points to its allocated elements.

So a struct containing an array doesn't contain a pointer. It contains, in your case, two ints plus the non-array int. Evidently your CPU is 32-bit, so it contains 12 bytes of data (three 4-byte ints). But some structure padding is added to make each item fall on an 8-byte boundary (for CPU access efficiency). That makes it 16 bytes long. There are compiler options to "pack" the structures so that no padding takes place. Typically #pragma pack(0) on a line by itself in the file, or a compiler command line option.

Comments

1

this gives an idea on the effect of packing on int and char

#include <stdio.h>

#pragma  pack (push, 1)
typedef struct {
    int a;
    int b[2];
}TEST1;

typedef struct {
    int a;
    int b[2];
    char c;
}TEST2;
#pragma pack(pop)

typedef struct {
    int a;
    int b[2];
}TEST3;

typedef struct {
    int a;
    int b[2];
    char c;
}TEST4;

int main(){
    printf(" ==== PAKED =====\t==== DEFAULT =====\n");
    printf("sizeof(TEST1)=%d \tsizeof(TEST3)=%d\n",sizeof(TEST1),sizeof(TEST3));
    printf("sizeof(TEST2)=%d \tsizeof(TEST4)=%d\n\n",sizeof(TEST2),sizeof(TEST4));

   return 0;
}

the output on my system (AMD 64 for most curious ;) )

 ==== PAKED =====       ==== DEFAULT =====
sizeof(TEST1)=12        sizeof(TEST3)=12
sizeof(TEST2)=13        sizeof(TEST4)=16

Press any key to continue...

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.