0

Possible Duplicate:
Why isn’t sizeof for a struct equal to the sum of sizeof of each member?

I can not understand why is it like this:

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

typedef struct
{
    char b;
    int a;
} A;

typedef struct
{
    char b;
} B;

int main() {
    A object;
    printf("sizeof char is: %d\n",sizeof(char));
    printf("sizeof int is: %d\n",sizeof(int));
    printf("==> the sizeof both are: %d\n",sizeof(int)+sizeof(char));
    printf("and yet the sizeof struct A is: %d\n",sizeof(object));
    printf("why?\n");

    B secondObject;
    printf("pay attention that the sizeof struct B is: %d which is equal to the "
            "sizeof char\n",sizeof(secondObject));

    return 0;
}

I think I explained my question in the code and there is no more need to explain. besides I have another question: I know there is allocation on the: heap/static heap/stack, but what is that means that the allocation location is unknown, How could it be ?

I am talking about this example:

    typedef struct
{
    char *_name;
    int   _id;
} Entry;

int main()
{
    Entry ** vec = (Entry**) malloc(sizeof(Entry*)*2);
    vec[0] = (Entry *) malloc(sizeof (Entry));
    vec[0]->_name = (char*)malloc(6);
    strcpy (vec[0]->_name, "name");
    vec[0]->_id = 0;
    return 0;
}

I know that: vec is on the stack. *vec is on the heap. *vec[0] is on the heap. vec[0]->id is on the heap.

but : vec[0]->_name is unknown why ?

Community
  • 1
  • 1
  • 1
    Read about [structure padding](http://en.wikipedia.org/wiki/Data_structure_alignment#Data_structure_padding). – Alok Save Feb 02 '13 at 13:24
  • What do you mean by *vec[0]->_name is unknown why* ? – cnicutar Feb 02 '13 at 13:25
  • By the way, `%d` cannot be used to print expressions of type `size_t`. You need `%zu`, or if your version of C is severely outdated or non-conforming, you need to look at its documentation for how to print `size_t` or else cast to `(int)` before printing. – R.. GitHub STOP HELPING ICE Feb 02 '13 at 13:25
  • `strcpy (vec[i]->_name, "name");` where is `i` declared? I can't see any `i` in your program. – Alok Save Feb 02 '13 at 13:26
  • you are right. I fixed it now – Suzan Plutu Feb 02 '13 at 13:28
  • 1
    I just fail to understand the mad rush for answering an exact duplicate with an elaborate, correct and time tested answer. – Alok Save Feb 02 '13 at 13:37
  • C has four storage durations: static, thread, automatic, and allocated. Which ones go where? It doesn't matter... Forget "stack" and "heap". ... and stop using a C++ compiler! I can tell because you're casting malloc, when that's unnecessary. – autistic Feb 02 '13 at 16:17
  • @SuzanPlutu, welcome on SO. Please search the site and read the FAQ before posting questions. – Jens Gustedt Feb 02 '13 at 17:18

4 Answers4

1

There is an unspecified amount of padding between the members of a structure and at the end of a structure. In C the size of a structure object is greater than or equal to the sum of the size of its members.

ouah
  • 142,963
  • 15
  • 272
  • 331
0

The compiler is free to add padding in structures to ensure that datatypes are aligned properly. For example, an int will be aligned to sizeof(int) bytes. So I expect the output for the size of your A struct is 8. The compiler does this, because fetching an int from an unaligned address is at best inefficient, and at worst doesn't work at all - that depends on the processor that the computer uses. x86 will fetch happily from unaligned addresses for most data types, but will take about twice as long for the fetch operation.

In your second code-snippet, you haven't declared i.

So vec[0]->_name is not unknown - it is on the heap, just like anything else you get from "malloc" (and malloc's siblings).

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
0

Take a look at this question as well as this one and many others if you search for CPU and memory alignment. In short, CPUs are happier if they access the memory aligned to the size of the data they are reading. For example, if you are reading a uint16_t, then it would be more efficient (on most CPUs) if you read at an address that is a multiple of 2. The details of why CPUs are designed in such a way is whole other story.

This is why compilers come to the rescue and pad the fields of the structures in such a way that would be most comfortable for the CPU to access them, at the cost of extra storage space. In your case, you are probably given 3 byte of padding between your char and int, assuming int is 4 bytes.

If you look at the C standard (which I don't have nearby right now), or the man page of malloc, you will see such a phrase:

The malloc() and calloc() functions return a pointer to the allocated memory that is suitably aligned for any kind of variable.

This behavior is exactly due to the same reason I mentioned above. So in short, memory alignment is something to care about, and that's what compilers do for you in struct layout and other places, such as layout of local variables etc.

Community
  • 1
  • 1
Shahbaz
  • 46,337
  • 19
  • 116
  • 182
0

You're running into structure padding here. The compiler is inserting likely inserting three bytes' worth of padding after the b field in struct A, so that the a field is 4-byte aligned. You can control this padding to some degree using compiler-specific bits; for example, on MSVC, the pack pragma, or the aligned attribute on GCC, but I would not recommend this. Structure padding is there to specify member alignment restrictions, and some architectures will fault on unaligned accesses. (Others might fixup the alignment manually, but typically do this rather slowly.)

See also: http://en.wikipedia.org/wiki/Data_structure_alignment#Data_structure_padding


As to your second question, I'm unsure what you mean by the name is "unknown". Care to elaborate?

sheu
  • 5,653
  • 17
  • 32