Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Memory layout for nested structure in c

Tags:

c

structure

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;
like image 770
sakthi Avatar asked Mar 16 '16 13:03

sakthi


People also ask

How are structures stored in memory C?

Struct members are stored in the order they are declared. (This is required by the C99 standard, as mentioned here earlier.) If necessary, padding is added between struct members, to ensure that the latter one uses the correct alignment. Each primitive type T requires an alignment of sizeof(T) bytes.

What is nested structure in C?

A nested structure in C is a structure within structure. One structure can be declared inside another structure in the same way structure members are declared inside a structure. Syntax: struct name_1.

What is memory segmentation in C?

When a program in C is executed, binary code is loaded into RAM and is segregated into five different areas which are text segment, initialized data segment, uninitialized data segment, command-line arguments, stack, and heap. Code instructions are stored in text segment and this is shareable memory.

What is BSS in memory layout?

bss segment stands for Block Started by symbol. The bss segment contains the object file where all the statically allocated variables are stored. Here, statically allocated objects are those objects without explicit initialization are initialized with zero value.


2 Answers

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:

enter image description here

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:

enter image description here

By the way, there is a discussion here covering related points in this topic.

like image 168
ryyker Avatar answered Oct 05 '22 19:10

ryyker


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

like image 31
Kumar2080 Avatar answered Oct 05 '22 19:10

Kumar2080