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.