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.
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.
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).
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
How to Find the Size of All Files Located Inside a Folder
Name Hiding and Fragile Base Problem
How to Force Inclusion of "Unused" Object Definitions in a Library
C++ Calculating More Precise Than Double or Long Double
Why Should I Avoid MACros in C++
C++ Convert from Lpctstr to Const Char *
Multiple Inheritance: Unexpected Result After Cast from Void * to 2Nd Base Class
Strange "Unsigned Long Long Int" Behaviour
How to Pass a Std::Function Object to a Function Taking a Function Pointer
Very Simple Application Fails with "Multiple Target Patterns" from Eclipse
Removing '#Include <Algorithm>' Doesn't Break the Code
How Should One Use Std::Optional
Why Can't C++11 Move a Noncopyable Functor to a Std::Function
Referencing Memory Operands in .Intel_Syntax Gnu C Inline Assembly