C Struct Sizes Inconsistence

C struct sizes inconsistence

Ever heard of alignment and padding?

Basically, to ensure fast access, certain types have to be on certain bounds of memory addresses.

This is called alignment.

To achieve that, the compiler is allowed to insert bytes into your data structure to achieve that alignment.

This is called padding.

What is the reason for seemingly inconsistent sizes of pointers and struct types?

For starters to output an object of the type size_t you shall use the conversion specifier zu

printf("sizeof(Person): %zu\n", sizeof(Person));
^^^

I don't understand the following: If sizeof(Person) == 16, why
sizeof(person) == 8 and not 16?

The name Person denotes the structure

typedef struct person{
char *name;
int age;
}Person;

An object of this type occupies 16 bytes.

The name person declared like

Person *person = (Person*)malloc(sizeof(Person));

denotes a pointer. This pointer occupies 8 bytes and points to a memory allocated for an object of the type Person that occupies 16 bytes.

That is sizeof( Person ) and sizeof( Person * ) that is equivalent to sizeof( person ) are two different expressions.

And if sizeof(buffer) == 32, why sizeof(person->name) == 8 and not 32?

Again the name name has a pointer type and occupies 8 bytes. It is a data member of the structure person declared like

char *name;

This pointer points to a dynamically allocated memory that occupies 32 bytes.

Pay attention to that the size of a pointer does not depend on whether it points to a single object or to the first element of an array. That is you can allocate memory for a very big array but nevertheless the size of the pointer pointing to the allocated memory will not be changed depending on the size of the allocated memory.

Consider for example

int a[10];

int *p = a;

int b[10000];

int *q = b;

In this example the pointers p and q have the same size. You could write for example

int a[10];

int *p = a;

int b[10000];

p = b;

The size of the pointer p will not be changed after the last assignment.

Why is the struct memory size inconsistent with my expectations?

Size and alignment guarantees:

For the numeric types, the following sizes are guaranteed:

type                                 size in bytes

byte, uint8, int8 1
uint16, int16 2
uint32, int32, float32 4
uint64, int64, float64, complex64 8
complex128 16

The following minimal alignment properties are guaranteed:

1. For a variable x of any type: unsafe.Alignof(x) is at least 1.

2. For a variable x of struct type: unsafe.Alignof(x) is the largest of all the values unsafe.Alignof(x.f) for each field f of x, but at least 1.

3. For a variable x of array type: unsafe.Alignof(x) is the same as the alignment of a variable of the array's element type.

A struct or array type has size zero if it contains no fields (or elements, respectively) that have a size greater than zero. Two distinct zero-size variables may have the same address in memory.

Then, read these:

Memory Layouts

Padding is hard - Dave Cheney

Explanation on 64 bit machine:

Your type is struct and its size depends on how underlying types were defined. Two structs with same fields but different order may have different sizes. Size of struct is counted accordingly with padding and alignment rules.

Struct alignment

Note: each colored box is one byte.

Try it here, and edit the struct then press the Ask button on top of the page.

Struct varies in memory size?

The compiler is allowed to add padding between struct members to make processing more efficient. This padding varies by platform, compiler version etc. It's one of the things that make sending structs over the network impossible.

You can use offsetof to find out where exactly your compiler is adding paddings.

C/C++ structure incomplete member type inconsistency?

Why does second struct definition doesn't cause any problem?

Because it is a pointer. The size of the pointer is known to the compiler even if the type the pointer is pointing to is incomplete.

Struct defined differently for C and C++ - is it safe? PC-Lint warns

Am I correct to assume that the header file containing this definition is included in several translation units, some of which are compiled as C++, and some -- as plain C?

If it is true, then you have an ODR violation, which, according to the C++ standard, invokes undefined behavior.

There are two ways to deal with it.

  1. Ignore this instance of undefined behavior, provided that you know how exactly it manifests on platform(s) you need to support. (Note that undefined behavior can manifest as a correctly working program). To tell the truth, with most compilers you will not have a problem here. However, you must understand that this code works by happenstance, not by the law. Compilers are permitted to use different layout for classes with member functions than without them. (I'm willing to bet that this code will break on CINT, for example).

  2. Eliminate undefined behavior. I'd suggest you to go this way. There are several possibilities to do it. For example, you can inherit "C++ Rect" from "C Rect", keeping the latter as a plain struct.



Related Topics



Leave a reply



Submit