C Sizeof char[] in struct [closed] - c

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I know what padding is and how alignment works. Given the struct below:
typedef struct {
char word[10];
short a;
int b;
} Test;
I don't understand how C interprets and aligns the char array inside the struct. It should be 9 chars + terminator and it should be regarded as the longest like this:
| - _ - _ - _ - _ - word - _ - _ - _ - _ - |
| - a - | - _ - b - _ - | padding the remaining 4 bytes
The "-" represents a byte and "_" separates the bytes. So we have the 10 bytes long word, the 2 bytes long a and the 4 bytes long b and padding of 4 bytes. But when I print sizeof(Test) it returns 16.
EDIT: I got it.

In a struct like
struct {
char word[10];
short a;
int b;
}
you have the following requirements:
a needs an even offset. As the char arry before it has an even length, there is no need for padding. So a sits at offset 10.
b needs an offset which is dividible by 4. 12 is dividible by 4, so 12 is a fine offset for b.
The whole struct needs a size which is dividible by 4, because every b in an array of this struct needs to have the said requirement. But as we are currently at size 16, we don't need any padding.
WWWWWWWWWWAABBBB
|-- 10 --| 2 4 = 16
Compare this with
struct {
char word[11];
short a;
int b;
}
Here, a would have offset 11. This is not allowed, thus padding is inserted. a is fine with an offset of 12.
b would then get an offset of 14, which isn't allowed either, so 2 bytes are added. b gets an offset of 16. The whole struct gets a size of 20, which is fine for all subsequent items in an array.
WWWWWWWWWWW.AA..BBBB
|-- 11 --|1 2 2 4 = 20
Third example:
struct {
char word[11];
int b;
short a;
}
(note the changed order!)
b is happy with an offset of 12 (it gets 1 padding byte),
a is happy with an offset of 16. (no padding before it.)
After the struct, however, 2 bytes of padding are added so that the struct aligns with 4.
WWWWWWWWWW..BBBBAA..
|-- 10 --| 2 4 2 2 = 20

In:
struct
{
char word[10];
short a;
int b;
}
and given two-byte short and four-byte int, the structure is laid out in memory:
Offset Member
0 word[0]
1 word[1]
2 word[2]
3 word[3]
4 word[4]
5 word[5]
6 word[6]
7 word[7]
8 word[8]
9 word[9]
10 a
11 a
12 b
13 b
14 b
15 b
To get the layout described in the question, where a and b overlap word, you need to use a struct inside a union:
typedef union
{
char word[10];
struct { short a; int b; };
} Test;

Generally, each variable will be aligned on a boundary of its size.
(unless attributes such as packed are applied)
A complete discussion is on Wikipedia, which says in part:
A char (one byte) will be 1-byte aligned.
A short (two bytes) will be 2-byte aligned.
An int (four bytes) will be 4-byte aligned.
A long (four bytes) will be 4-byte aligned.
A float (four bytes) will be 4-byte aligned.
A double (eight bytes) will be 8-byte aligned on Windows and 4-byte aligned on
Linux (8-byte with -malign-double compile time option).
A long long (eight bytes) will be 4-byte aligned.
So your structure is laid out as:
typedef struct {
char word[10];
// Aligned with beginning of structure; takes bytes 0-9
short a;
// (assuming short is 2-bytes)
// Previous member ends on byte 9, this one starts on byte-10.
// Byte 10 is a multiple of 2, so no padding necessary
// Takes bytes 10 and 11
int b;
// Previous member ends on byte 11, next byte is 12, which is a multiple of 4.
// No padding necessary
// Takes bytes 12, 13, 14, 15.
} Test;
Total size: 16 bytes.
If you want to play with it, change your word-array to 9 or 11 bytes,
or reverse the order of your short and int, and you'll see the size of the structure change.

Related

It will give the output 28 on DEV c++ compiler I am expecting 26 considering float as 4 byte int as 4 byte and char as 1 byte [duplicate]

This question already has answers here:
Structure padding and packing
(11 answers)
Closed 7 years ago.
struct
{
int m,s,l;
union
{
char c[10];
};
float p;
} a;
int main()
{
printf("%d",sizeof(a));
return 0;
}
according to the calculations ans must be 4*3+10+4=26 but DEV C++ compiler showing the output 28.
The principles of allocating local variables on stack are roughly the same for all systems
1 -- Stack grows from high addresses to low addresses
2 -- The order of declaration of your variables in your program corresponds to growth of stack
3 -- Each type has alignment - the address of any variable must be divisible by its size (1 for char, 2 for short, etc).Try to waste as little space as possible
In this way, we try to use some waste space to improve the speed of memory access.
So in your codes, it meams that
#include <stdio.h>
#include <stdlib.h>
struct // the base address is &a
{
int m; // [0, 4)
int s; // [4, 8)
int l; // [8, 12)
union
{
char c[10]; // [12, 22)
};
// char m_align[2] // there are 4 byte for align
float p; // [24, 28)
}a; // sizeof = 28
the value m is begin at the start of type a, and occupancy 4 byte in 32bit system, so it's address is [0, 4). and it's start address can divisible by sizeof(int).
this is the same to s and l.
and then the union value c[10] occupancy, occupancy [12, 22), the begining od it's address 12 can divisible by sizeof(int).
What's importment the next address is 22, and the value p will occupancy sizeof(float) = 4 bytes,but the address 22 can't divisible by sizeof(float). we must fill the space to alignment the struct and try to waste as little space as possible. So the base address of value p will be 24 which can divisible by sizeof(float), so the adddress of p is [24, 28]...
you can see this https://en.wikipedia.org/wiki/Data_structure_alignment for detail
The members in the structure arranged as a group of 4 bytes in 32 bit processor.So you are getting 28 bytes as size.
for more details see here
It is due to padding

Why is struct containing single char not padded to size 4 on a 32-bit system? [duplicate]

This question already has answers here:
Structure Padding
(6 answers)
Closed 7 years ago.
struct test {
char c;
} x;
From my knowledge of structure padding, I expected the size of this structure to be 4 Bytes on a 32-bit system. Why does it show 1 byte?
You just have a char, in that case you won't need any alignment/padding.
If you try this you should see some alignment:
char *p; /* 4 or 8 bytes */
char c; /* 1 byte */
//char pad[3]; /* 3 bytes */
int x; /* 4 bytes */
There are different rules for different architectures, in this case the int has a 4byte alignment, which forces a padding of three bytes to be added.
source:
http://www.catb.org/esr/structure-packing/
In C, the strucute are padded to the current data size.
If you have a char will be aligned to 1B, for short to 2B and so on.
A quick rule is: size of previous elements + size of current element aligned to size of current element .
Here are some exaples:
struct
{
int a1; // 0 + 4 aligned to 4 => 4
char a2; // 4 + 1 aligned to 1 => 5
} // total size 5
struct
{
char a1; // 0 + 1 aligned to 1 => 1
int a2; // 1 + 4 aligned to 4 => 8
}
struct
{
char a1; // 0 + 1 aligned to 1 => 1
short a2; // 1 + 2 aligned to 2 => 4
int a3; // 4 + 4 aligned to 4 => 8
}
This rule is an effect of memory addressing:
Fastest way to read/write X byte memory is if that memory address is multiple of X. (This is how Intel processors optimise memory access by ignoring some bits of addressing).
Another padding is between structures in memory. If you have a structure with an int and a char(total size 5), in memory you will still have 3 bytes padding between them for memory access optimisation.

Sizeof a struct in C

Well, after reading this Size of structure with a char, a double, an int and a t I still don't get the size of my struct which is :
struct s {
char c1[3];
long long k;
char c2;
char *pt;
char c3;
}
And sizeof(struct s) returns me 40
But according to the post I mentioned, I thought that the memory should like this way:
0 1 2 3 4 5 6 7 8 9 a b c d e f
+-------------+- -+---------------------------+- - - - - - - -+
| c1 | |k | |
+-------------+- -+---------------------------+- - - - - - - -+
10 11 12 13 14 15 16 17
+---+- -+- -+- - - - - -+----+
|c2 | |pt | | c3 |
+---+- -+- -+- - - - - -+----+
And I should get 18 instead of 40...
Can someone explain to me what I am doing wrong ? Thank you very much !
Assuming an 8-byte pointer size and alignment requirement on long long and pointers, then:
3 bytes for c1
5 bytes padding
8 bytes for k
1 byte for c2
7 bytes padding
8 bytes for pt
1 byte for c3
7 bytes padding
That adds up to 40 bytes.
The trailing padding is allocated so that arrays of the structure keep all the elements of the structure properly aligned.
Note that the sizes, alignment requirements and therefore padding depend on the machine hardware, the compiler, and the platform's ABI (Application Binary Interface). The rules I used are common rules: an N-byte type (for N in {1, 2, 4, 8, 16 }) needs to be allocated on an N-byte boundary. Arrays (both within the structure and arrays of the structure) also need to be properly aligned. You can sometimes dink with the padding with #pragma directives; be cautious. It is usually better to lay out the structure with the most stringently aligned objects at the start and the less stringently aligned ones at the end.
If you used:
struct s2 {
long long k;
char *pt;
char c1[3];
char c2;
char c3;
};
the size required would be just 24 bytes, with just 3 bytes of trailing padding. Order does matter!
The size of the structure depends upon what compiler is used and what compiler options are enabled. The C language standard makes no promises about how memory is utilized when the compiler creates structures, and different architectures (for example 32-bit WinTel vs 64-bit WinTel) cause different layout decisions even when the same compiler is used.
Essentially, the size of a structure is equal to the sum of the size of the bytes needed by the field elements (which can generally be calculated) plus the sum of the padding bytes injected by the compiler (which is generally not known).
It is because of alignment, gcc has
#pragma pack(push,n)
// declare your struct here
#pragma pack(pop)
to change it. Read here, and also __attribute__((__packed__)).
If you declare the struct
struct packed
{
char c1[3];
long long k;
char c2;
char *pt;
char c3;
} __attribute__((__packed__));
then compiling with gcc, sizeof(packed) = 18 since
c1: 3
k : 8
c2: 1
pt: 4 // it depends
c3: 1
Apparently Visual C++ compiler supports #pragma pack(push,n) too.
what is a size of structure?
#include <stdio.h>
struct {
char a;
char b;
char c;
}st;
int main()
{
printf("%ld", sizeof(st));
return 0;
}
it shows 3 in gdb compiler.

memory allocation for structures elements

Hi I am having difficulties in understanding about how the memory is allocated to the structure elements.
For example if i have the below structure and the size of char is 1 and int is 4 bytes respectively.
struct temp
{
char a;
int b;
};
I am aware that the size of the structure would be 8. Because there will be a padding of 3 bytes after the char, and the next element should be placed in multiple of 4 so the size will be 8.
Now consider the below structure.
struct temp
{
int a; // size is 4
double b; // size is 8
char c; // size is 4
double d; // size is 8
int e; // size is 4
};
This is the o/p i got for the above strucure
size of node is 40
the address of node is 3392515152 ( =: base)
the address of a in node is 3392515152 (base + 0)
the address of b in node is 3392515160 (base + 8)
the address of c in node is 3392515168 (base + 16)
the address of d in node is 3392515176 (base + 24)
the address of e in node is 3392515184 (base + 32)
The total memory sum up to 36 bytes, why does it show as 40 bytes?
If we create an array of such structure also the first element of the next array element can be place in 3392515188 (base + 36) as it is a multiple of 4, but why is it not happening this way?
Can any one plz solve my doubt.
Thanks in advance,
Saravana
It seems that on your system, double has to have the alignment of 8.
struct temp {
int a; // size is 4
// padding 4 bytes
double b; // size is 8
char c; // size is 1
// padding 7 bytes
double d; // size is 8
int e; // size is 4
// padding 4 bytes
};
// Total 4+4+8+1+7+8+4+4 = 40 bytes
Compiler adds an extra 4 bytes to the end of struct to make sure that array[1].b will be properly aligned.
Without end padding (assuming array is at address 0):
&array[0] == 0
&array[1] == 36
&array[1].b == 36 + 8 == 44
44 % 8 == 4 -> ERROR, not aligned!
With end padding (assuming array is at address 0):
&array[0] == 0
&array[1] == 40
&array[1].b == 40 + 8 == 48
48 % 8 == 0 -> OK!
Note that sizes, alignments, and paddings depend on target system and compiler in use.
In your calculation, you ignore the fact that e is subject to be padded as well:
The struct looks like
0 8 16 24 32
AAAAaaaaBBBBBBBBCcccccccDDDDDDDDEEEEeeee
where uppercase is the variable itself, and lowercase is the padding applied to it.
As you see (and as well from the addresses), each field is padded to 8 bytes, which is the largest field in the structure.
As the structure might be used in an array, and all array elements should be well-aligned as well, the padding to e is necessary.
It's heavily dependent on both your processor architecture and compiler. Modern machines and compilers may choose larger or smaller padding to reduce the access cost to data.
Four-byte alignment means that two address lines are unused. Eight, three. A chip can use that to address more memory (coarser grain) with the same amount of hardware.
A compiler might use a similar trick for various reasons, but no compiler is required to do anything but be no less fine-grained than the processor. Often, they'll just take the biggest-size value and use it exclusively for that block. In your case, that's a double, which is eight bytes.
This is a compiler dependent behavior.
Some compiler makes that 'double' to be stored after 8 bit offset.
IF you modify the structure as below you will get different result.
struct temp
{
double b; // size is 8
int a; // size is 4
int e; // size is 4
double d; // size is 8
char c; // size is 4
}
Every programmer should know what padding you compiler is doing.
E.g. If you are working on ARM platform and you set compiler settings to do not pad structure elements[ then accessing structure elements through pointers may generate 'odd' address for which processor generates an exception.
Every structure will also have alignment requirements
for example :
typedef struct structc_tag
{
char c;``
double d;
int s;
} structc_t;
Applying same analysis, structc_t needs sizeof(char) + 7 byte padding + sizeof(double) + sizeof(int) = 1 + 7 + 8 + 4 = 20 bytes. However, the sizeof(structc_t) will be 24 bytes. It is because, along with structure members, structure type variables will also have natural alignment. Let us understand it by an example. Say, we declared an array of structc_t as shown below structc_t structc_array[3];
Assume, the base address of structc_array is 0×0000 for easy calculations. If the structc_t occupies 20 (0×14) bytes as we calculated, the second structc_t array element (indexed at 1) will be at 0×0000 + 0×0014 = 0×0014. It is the start address of index 1 element of array. The double member of this structc_t will be allocated on 0×0014 + 0×1 + 0×7 = 0x001C (decimal 28) which is not multiple of 8 and conflicting with the alignment requirements of double. As we mentioned on the top, the alignment requirement of double is 8 bytes. In order to avoid such misalignment, compiler will introduce alignment requirement to every structure. It will be as that of the largest member of the structure. In our case alignment of structa_t is 2, structb_t is 4 and structc_t is 8. If we need nested structures, the size of largest inner structure will be the alignment of immediate larger structure.
In structc_t of the above program, there will be padding of 4 bytes after int member to make the structure size multiple of its alignment. Thus the sizeof (structc_t) is 24 bytes. It guarantees correct alignment even in arrays. You can cross check
to avoid structure padding!
#pragma pack ( 1 ) directive can be used for arranging memory for structure members very next to the end of other structure members.
#pragma pack(1)
struct temp
{
int a; // size is 4
int b; // size is 4
double s; // size is 8
char ch; //size is 1
};
size of structure would be:17
If we create an array of such structure also the first element of the next array element can be place in 3392515188 (base + 36) as it is a multiple of 4, but why is it not happening this way?
It can't because of the double elements in there.
It's clear that the compiler and architecture you are using requires a double to be eight byte aligned. This is obvious because there is seven bytes of padding after the char c.
This requirement also means that the entire struct must be eight byte aligned. There's no point in carefully making all the doubles aligned to eight bytes relative to the start of the struct if the struct itself is only four byte aligned. Hence the padding after the final int to make sizeof(temp) a multiple of eight.
Note that this alignment requirement need not be a hard requirement. The compiler could choose to do the alignment even if doubles can be four byte aligned on the grounds that it might take more memory cycles to access the double if it's only four byte aligned.

How is sizeof structures found? [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)
Closed 9 years ago.
I am getting 56 bytes for the following. Can anyone explain how is that?
#include <stdio.h>
typedef struct how_many_bytes {
long s[4];
char c, e;
int i[2];
char *d;
} How_Many_Bytes;
int main(){
printf("%lu ", sizeof(How_Many_Bytes));
}
Shouldn't it be (4*8) + 1 + 1 + 2(for padding) + 4 + 4 + 8 = 52 bytes
Because it's a 64-bit machine, so the padding is 6 instead of 2 in your calculation.
Also, you should use %zu to print size_t.
Your analysis is correct, except that there is an additional 4 bytes padding before the char *d member. This is so that the d member is aligned on an 8-byte boundary.
The pahole output for this structure on x86-64 is:
struct how_many_bytes {
long int s[4]; /* 0 32 */
char c; /* 32 1 */
char e; /* 33 1 */
/* XXX 2 bytes hole, try to pack */
int i[2]; /* 36 8 */
/* XXX 4 bytes hole, try to pack */
char * d; /* 48 8 */
/* size: 56, cachelines: 1 */
/* sum members: 50, holes: 2, sum holes: 6 */
/* last cacheline: 56 bytes */
}; /* definitions: 1 */
No matter how you rearrange the members of this structure, you won't be able to do better than 6 bytes in total of padding. The sum of the sizes of the members is 50 bytes, and the maximum alignment of the structure members is 8, so even if you arrange the members in the optimal order there will be 6 bytes of padding at the end of the structure to round its size up to the next biggest multiple of 8.

Resources