C++ : Size of structure? [duplicate] - c++

This question already has answers here:
Why isn't sizeof for a struct equal to the sum of sizeof of each member?
(13 answers)
Closed 5 years ago.
My c++ code
#include <iostream>
using namespace std ;
struct Node {
int data ;
struct Node *next;
};
int main(){
struct Node *head = NULL;
struct Node *second = NULL;
cout << sizeof(struct Node);
}
output to terminal
16
How is the size 16 ?
Size of int is 4bytes.
How come it's multiplied by 4 ?
Please can anyone give detailed calculation ?
Thanks !

An int is indeed 4 bytes (at least in x86 64 bit machines). A pointer (at least in x86 64 bit machines) is 8 bytes, so in theory the struct could have been 12 bytes. However, it's padded to a multiplication of the native word size (8 bytes) - and the closet round-up of 12 bytes would be 16 bytes.

Structures are packed to the size of "biggest word" used. Eg, if you have such structure:
struct ThreeBytes {
char one;
short two;
};
Its size will be 4 bytes, because field one will be padded to the size of short, i.e. there is unused byte after that filed. If two would be an int, the structure will have size of two ints. This happens if you align your structure to that:
// this structure got size of 4 bytes.
struct ThreeBytes {
char one;
char two;
short three;
};
And this is unaligned one:
// This structure will have size 6
struct ThreeBytes {
char one;
short two;
char three;
};
This is default behavior, there are compiler directives that allow change packing (see #pragma pack, for example, compiler means may be different). Essentially you can set the unit to which fields will be padded or disable padding by setting it to 1. But some platforms do not allow that at all.

Related

Why the size of my Person is 10 bytes, and not 16 ? [duplicate]

Someone explain me how does the order of the member declaration inside a class determines the size of that class.
For Example :
class temp
{
public:
int i;
short s;
char c;
};
The size of above class is 8 bytes.
But when the order of the member declaration is changed as below
class temp
{
public:
char c;
int i;
short s;
};
then the size of class is 12 bytes.
How?
The reason behind above behavior is data structure alignment and padding. Basically if you are creating a 4 byte variable e.g. int, it will be aligned to a four byte boundary i.e. it will start from an address in memory, which is multiple of 4. Same applies to other data types. 2 byte short should start from even memory address and so on.
Hence if you have a 1 byte character declared before the int (assume 4 byte here), there will be 3 free bytes left in between. The common term used for them is 'padded'.
Data structure alignment
Another good pictorial explanation
Reason for alignment
Padding allows faster memory access i.e. for cpu, accessing memory areas that are aligned is faster e.g. reading a 4 byte aligned integer might take a single read call where as if an integer is located at a non aligned address range (say address 0x0002 - 0x0006), then it would take two memory reads to get this integer.
One way to force compiler to avoid alignment is (specific to gcc/g++) to use keyword 'packed' with the structure attribute. packed keyword Also the link specifies how to enforce alignment by a specific boundary of your choice (2, 4, 8 etc.) using the aligned keyword.
Best practice
It is always a good idea to structure your class/struct in a way that variables are already aligned with minimum padding. This reduces the size of the class overall plus it reduces the amount of work done by the compiler i.e. no rearrangement of structure. Also one should always access member variables by their names in the code, rather than trying to read a specific byte from structure assuming a value would be located at that byte.
Another useful SO question on performance advantage of alignment
For the sake of completion, following would still have a size of 8 bytes in your scenario (32 bit machine), but it won't get any better since full 8 bytes are now occupied, and there is no padding.
class temp
{
public:
int i;
short s;
char c;
char c2;
};
class temp
{
public:
int i; //size 4 alignment 4
short s; //size 2 alignment 2
char c; //size 1 alignment 1
}; //Size 8 alignment max(4,2,1)=4
temp[i[0-4];s[4-2];c[6-7]]] -> 8
Padding in (7-8)
class temp
{
public:
char c; //size 1 alignment 1
int i; //size 4 alignment 4
short s; //size 2 alignment 2
};//Size 12 alignment max(4,2,1)=4
temp[c[0-1];i[4-8];s[8-10]]] -> 12
Padding in (1-4) and (10-12)

Struct size stays the same even after adding a new member to it

when is simply execute
cout << sizeof(string);
i got 8 as answer.
now i am having a structure
typedef struct {
int a;
string str;
} myType;
and i am executing
cout << sizeof(myType);
i got 16 as the answer.
now i made a change in my structure
typedef struct {
int a, b;
string str;
} myType;
and i am executing
cout << sizeof(myType);
i got 16 as the answer!!!. How? What is happening?
Perhaps padding is happening. E.g. sizeof(int) can be 4 bytes and compiler can add 4 bytes after a for the sake of data alignment. The layout could be like this:
typedef struct {
int a; // 4 bytes
// 4 bytes for padding
string str; // 8 bytes
} myType;
typedef struct {
int a; // 4 bytes
int b; // 4 bytes
string str; // 8 bytes
} myType;
Looks like 8 byte alignment.
So if you have any data type that has less than 8 bytes, it will still use 8 bytes.
I assume the pointer is 8 byte, whereas the ints are only 4 bytes each.
You can force 1 byte alignment using code like outlined here Struct one-byte alignment conflicted with alignment requirement of the architecture? . You should then get different size for first case.
It's called structure packing to achieve optimal memory alignment.
See The Lost Art of C Structure Packing to understand the how and why. It's done the same way in both C and C++.
In C/C++ structs are "packed" in byte chunks. You can specify which size your structs should be packed.
Here a reference: http://msdn.microsoft.com/en-us/library/2e70t5y1.aspx

sizeof(struct) weird output in C++ [duplicate]

This question already has answers here:
Why isn't sizeof for a struct equal to the sum of sizeof of each member?
(13 answers)
Memory alignment in C-structs
(10 answers)
Memory overhead for structs with pointers in C [duplicate]
(1 answer)
Closed 9 years ago.
Could somebody please explain the output of this code?
#include <iostream>
using namespace std;
struct Yo{
char sex;
int a;
};
int main() {
Yo c;
cout<<sizeof(c.sex);
cout<<endl<<sizeof(c.a);
cout<<endl<<sizeof(c);
return 0;
}
Output: 1 4 8
How is the size of structure 8?
This is memory alignment.
struct Yo{
char sex; // Takes up 1 byte + 3 for padding
int a; // Takes up 4 bytes
};
The three bytes between sex and a won't be used because the compiler aligns them for better performance. Thus sex ends up using 1 byte of space and the three bytes after the member variable are used as padding to ensure that int a has an address multiple of 4 (it is 4 byte aligned).
Because of structure padding (aka memory alignment). The alignment has to be a power of two (C11 makes this explicit in 6.2.8p4 as stated by #KeithThompson) and because the total size of your structure is 5, the nearest multiple of 4 is 8 so it gives 8, also because the alignment has to be a power of two.
You can use #pragma pack to have the exact size.
#pragma pack(push, 1) /* set alignment to 1 byte boundary */
struct A {
char s;
int a;
};
#pragma pack(pop) // restore to default
Warning: #pragma pack is not in standard C, nor is the assumption that the structure requires 4-byte alignment. As #KeithThompson stated.
"The size of a type must be a multiple of its alignment, but the size needn't be a power of 2. For example, assuming 4-byte int, a structure like struct { int a, b; char d; } will likely have an alignment of 4 and a size of 12. The size is the nearest multiple of the alignment, not the nearest power of 2." - #KeithThompson
Packing is useful to decrease memory, use it when you have a structure full of integers, fixed char lengths, etc. I do not know if it's good to use with pointers but I do not see it useful when using a pointer (e.g. a void * in the struct).
Read more here

what does this mean in c int a:16;? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What does 'unsigned temp:3' mean?
please what does this notation mean
int a:16;
I found it is code like this and it does compile.
struct name {
int a:16; }
This is a bitfield.
This particular bitfield doesn't make much sense as you just could use a 16-bit type and you're wasting some space as the bitfield is padded to the size of int.
Usually, you are using it for structures that contain elements of bit size:
struct {
unsigned nibble1 : 4;
unsigned nibble2 : 4;
}
struct name { int a:16; }
It means a is defined as 16-bit memory space. The remaining bits (16 bits) from int can be used to defined another variable, say b, like this:
struct name { int a:16; int b:16; }
So if int is 32-bit (4 bytes), then the memory of one int is divided into two variables a and b.
PS: I'm assuming sizeof(int) = 4 bytes, and 1 byte = 8 bits
struct s
{
int a:1;
int b:2;
int c:7;
};/*size of structure s is 4 bytes and not 4*3=12 bytes since all share the same space provided by int declaration for the first variable.*/
struct s1
{
char a:1;
};/*size of struct s1 is 1byte had it been having any more char _var:_val it would have been the same.*/
It's a bitfield.
I've never seen a 16 bit bitfield; usually that's a short.
http://www.cs.cf.ac.uk/Dave/C/node13.html

struct size is different from typedef version?

I have the following struct declaration and typedef in my code:
struct blockHeaderStruct {
bool allocated;
unsigned int length;
};
typedef struct blockHeaderStruct blockHeader;
When I do sizeof(blockheader), I get the value of 4 bytes back, but when I do sizeof(struct blockHeaderStruct), I get 8 bytes.
Why is this happening? Why am I not getting 5 back instead?
Firstly, you cannot do sizeof(blockHeaderStruct). That simply will not compile. What you can do is sizeof(struct blockHeaderStruct), which could indeed give you 8 bytes as result.
Secondly, getting a different result from sizeof(blockheader) is highly unlikely. Judging by your reference to sizeof(blockHeaderStruct) (which, again, will not even compile) your description of the problem is inaccurate. Take a closer look at what is it you are really doing. Most likely, you are taking a sizeof of a pointer type (which gives you 4), not a struct type.
In any case, try posting real code.
Looking at the definition of your struct, you have 1 byte value followed by 4 byte Integer. This integer needs to be allocated on 4 byte boundary, which will force compiler to insert a 3 byte padding after your 1 byte bool. Which makes the size of struct to 8 byte. To avoid this you can change order of elements in the struct.
Also for two sizeof calls returning different values, are you sure you do not have a typo here and you are not taking size of pointer or different type or some integer variable.
The most likely scenario is that you are actually looking at the size of a pointer, not the struct, on a 32-bit system.
However, int may be 2 bytes (16 bits). In that case, the expected size of the structure is 4:
2 bytes for the int
1 byte for the bool
round up to the next multiple of 2, because the size of the struct is usually rounded to a multiple of the size of its largest primitive member.
Nothing could explain sizeof(blockHeaderStruct) != sizeof(struct blockHeader), though, given that typedef. That is completely impossible.
Struct allocation normally occurs on a 4 byte boundary. That is the compiler will pad data types within a struct up to the 4 byte boundary before starting with the next data type. Given that this is c++ (bool is a sizeof 1) and not c (bool needs to be #define as something)
struct blockHeaderStruct {
bool allocated; // 1 byte followed by 3 pad bytes
unsigned int length; // 4 bytes
};
typedef struct blockHeaderStruct blockHeader;
typedef struct blockHeaderStruct *blockHeaderPtr;
A sizeof operation would result:
sizeof(blockHeader) == 8
sizeof(struct blockHeader) == 8
sizeof(blockHeaderPtr) == 4
(Note: The last entry will be 8 for a
64 bit compiler. )
There should be no difference in sizes between the first two lines of code. A typedef merely assigns an alias to an existing type. The third is taking the sizeof a pointer which is 4 bytes in a 32 bit machine and 8 bytes on a 64 bit machine.
To fix this, simply apply the #pragma pack directive before a structure is defined. This forces the compiler to pack on the specified boundary. Usually set as 1,2,or 4 (although 4 is normally the default and doesn't need to be set).
#include <stddef.h>
#include <stdio.h>
#pragma pack(1)
struct blockHeaderStruct {
bool allocated;
unsigned int length;
};
typedef struct blockHeaderStruct blockHeader;
int main()
{
printf("sizeof(blockHeader) == %li\n", sizeof(blockHeader));
printf("sizeof(struct blockHeader) == %li\n", sizeof(struct blockHeaderStruct));
return 0;
}
Compiled with g++ (Ubuntu
4.4.1-4ubuntu9) 4.4.1
Results in:
sizeof(blockHeader) == 5
sizeof(structblockHeader) == 5
You don't normally need this directive. Just remember to pack your structs efficiently. Group smaller data types together. Do not alternate < 4 byte datatypes and 4 byte data types as your structs will be mostly unused space. This can cause unnecessary bandwidth for network related applications.
I actually copied that snippet direct
from my source file.
OK.
When I do sizeof(blockheader), I get
the value of 4 bytes back
It looks like blockheader is typedef'ed somewhere and its type occupies 4 bytes or its type requires 4 byte alignment.
If you try sizeof(blockHeader) you'll get your type.
when I do sizeof(blockHeaderStruct), I
get 8 bytes.
The reason why alignment matters is that if you need an array of blockHeaders then you can compute how much memory you need. Or if you have an array and need to compute how much memory to copy, you can compute it.
If you want to align all struct members to addresses that are multiples of 1 instead of 4 or instead of your compiler's defaults, your compiler might offer a #pragma to do it. Then you'll save memory but accesses might be slower in order to access unaligned data.
Some compilers will optimize to always allocate data by powers of 2 (4 stays 4, but 5 is rounded up to 8).