Reputation: 705
I understand the structure's concept in C. I also understand how the structure is stored in memory. So I have created follwoing stuff:
struct tag1 {
char a;
int b;
}var1;
The size of the structure is 8 bytes(in gcc).
Memory layout example.
-----------
| | | | | ---> char a (only 1 byte is used and remaining 3 bytes are padding)
-----------
| | | | | ---> int b (4 byte is used)
-----------
Now i have some doubt in this sample program. How the nested structure is stored in memory.
struct tag1{
int a;
struct tag2{
long b;
}var1;
}var2;
Upvotes: 8
Views: 3071
Reputation: 23236
As noted in comments, the exact layout of a struct in memory is implementation specific. Also generally true, layout is affected by member types, memory addressing (32bit or 64bit) and pragma pack
calls that adjust the way alignment occurs along memory boundaries.
An example of what I see on my system when I place two instances of your original struct as sub-struct members into yet another struct (for context, and to force contiguous memory assignment), then assigned values to an instance of that struct to provide distinguishable (non-zero) content in the memory layout:
(32bit addressing, with no pragma statements)
typedef struct tag1{
int a;
struct tag2{
long b;
}var1;
}var2;
typedef struct {
var2 s1;
var2 s2;
}S;
In main:
S x = {0};
x.s1.a = 1;
x.s1.var1.b = 2;
x.s2.a = 3;
x.s2.var1.b = 4;
Memory for struct S
depicted on first line of image:
Note there is no additional memory usage required directly due to the struct or even sub-struct constructs. But indirectly, there can be (and often will be) additional memory required for alignment padding. This occurs when data types contained in the struct definition are of differing sizes and do not align naturally along addressing boundaries. When this occurs, padding will effect the computed sizeof
a struct
.
You can see that the size of each instance of your original struct is 8, (16 for two instances) and because int
and long
both align perfectly (and are the same size) in this instance, there appears to be no padding. Iflong
were replaced with long long
this would no longer be the case. Padding would almost certainly be required.
To provide context for the information below, relevant data sizes on my machine (compiled for 32bit) are:
int sizeChar = sizeof(char); //1 (always)
int sizeInt = sizeof(int); //4
int sizeLong = sizeof(long); //4
int sizeLL = sizeof(long long);//8
There will be more visible evidence of padding and the effects of pragma using a wider range of types. The following struct contains 4 data types:
typedef struct tag1 {
char a;
int b;
long c;
long long d;
}var1;
Using this struct definition, it is interesting to view the difference in padding caused by using pragma pack
calls. On my machine, and compiling for 32bit memory mapping, here is what I see:
By the way, there is a discussion here covering related points in this topic.
Upvotes: 6
Reputation: 16157
To figure out how the nested structure is stored in memory, you can run the code below:
#include <stdio.h>
#include <limits.h>
#include <stddef.h>
struct tag1{
int a;
struct tag2{
long b;
} var1;
} var2;
int main(void){
printf("CHAR_BIT is\t\t\t\t%d\n", CHAR_BIT);
puts("");
printf("sizeof var2 is\t\t\t\t%zu\n", sizeof var2);
printf("sizeof var2.var1 is\t\t\t%zu\n", sizeof var2.var1);
printf("sizeof var2.var1.b is\t\t\t%zu\n", sizeof var2.var1.b);
puts("");
printf("offsetof(struct tag1, a) is\t\t%zu\n", offsetof(struct tag1, a));
printf("offsetof(struct tag1, var1) is\t\t%zu\n", offsetof(struct tag1, var1));
printf("offsetof(struct tag1, var1.b) is\t%zu\n", offsetof(struct tag1, var1.b));
printf("offsetof(struct tag2, b) is\t\t%zu\n", offsetof(struct tag2, b));
return 0;
}
I'm asking you to run this code on your implementation, rather than giving you an direct answer, because:
sizeof (long) == 1
and CHAR_BIT == 32
?#pragma pack(n)
On my implementation (clang under OS X), the output is:
CHAR_BIT is 8
sizeof var2 is 16
sizeof var2.var1 is 8
sizeof var2.var1.b is 8
offsetof(struct tag1, a) is 0
offsetof(struct tag1, var1) is 8
offsetof(struct tag1, var1.b) is 8
offsetof(struct tag2, b) is 0
Well, it does not seem neat here, but it's nicely-formatted when showing up on my screen.
So (for my implementation) the memory layout of struct tag1
will be like this:
-----------------------
| | | | | | | | | ---> int a (8 bytes are used)
-----------------------
| | | | | | | | | ---> struct tag2 / long b (8 bytes are used)
-----------------------
Upvotes: 0
Reputation: 105
How the nested structure is stored in memory?
struct tag1{
int a;
struct tag2{
long b;
}var1;
}var2;
First of all you need to check the machine word size (i.e either 32-bit/64-bit) & on which gcc compiler is installed. Depending upon the architectures, the variables memory allocation will be varying. sizeof operator will return the variables size according to system specific.
For example(with padding) variables stored in memory
in 32-bit machines int & long both are allocating 4-bytes.
|var2.var1.b|==>0x601058
| var2.a |==>0x601054
in 64-bit machines int allocates 4-bytes & long allocates 8-bytes.
|var2.var1.b|==>0x601058
| var2.a |==>0x601050
Memory alignment of structure members is explained here Alignment in c
Upvotes: 2