Memory allocation for structure members

Posted by d99kg on Sat, 25 Dec 2021 01:18:20 +0100

Structure memory allocation

For example, as shown in the following figure, there seems to be no difference except for the structure name, and there should be no difference in memory size and memory distribution,

But in fact:

 sizeof(A) = 9
 sizeof(B) = 16

This difference is caused by memory alignment. Why there is memory alignment and what memory alignment is are not explained here. You can do it yourself. Anyway, the purpose is to speed up performance. The rules of memory alignment are as follows, which are also the rules followed by the compiler when opening memory for structures:

1. The offset of the first member relative to the first address of the structure is 0
2. The offset of each member relative to the first address is an integer multiple of the alignment value and the smaller value of the member type length
3. When no alignment value is specified, the default alignment value is the longest value of the structure member type as the alignment value
4. The total size of the structure, which is an integral multiple of the alignment value.

This rule confirms the memory distribution and memory size of structure members. In the above figure, structure A specifies that the memory alignment is 1 byte alignment. Then, according to rule A, the distribution of members is as follows:

B is the default alignment. Obviously, the alignment value is the length of type int, assuming 4. The memory allocation is as follows:

Why is it so distributed? We try to allocate memory to each member

  • c1: the allocated memory is 1 byte, occupying the position with index "0"
  • i: Allocate 4 bytes in length, but according to rule 2, there must be an integer multiple offset of 4 from the first address, so I is the starting position, "4", and the length is 4
  • c2: allocate 1 byte and occupy the position with index "8". s2: allocate 2 bytes. According to rule 2, the offset is 2 multiples, starting with "10" and length is 2
  • c3: allocate 1 byte to occupy the position with index "12". According to rule 4, the total length needs to be a multiple of 4, so 3 additional bytes are needed

Therefore, the total length of B is 16, in which part of the memory is unused, which can be said to be wasteful, but reasonable
The following is a test verification code:

#include <iostream>
#include <new>
#include <cstdio>
using namespace std;

#pragma pack(1)
struct A
{
public:
    char c1;
    int i;
    char c2;
    short s1;
    char c3;
};
#pragma pack()

struct B
{
    char c1;
    int i;
    char c2;
    short s1;
    char c3;
};
void printA(A a){

    cout<<"A:"<<a.c1<<","<<a.i<<","<<a.c2<<","<<a.s1<<","<<a.c2<<","<<a.c3<<endl;
    int h1 = 0x000000ff & a.i;
    int h2 = 0x000000ff & (a.i >>8);
    int h3 = 0x000000ff & (a.i >>16);
    int h4 = 0x000000ff & (a.i >>24);
    cout<<"h1:"<<h1<<" h2:"<<h2<<" h3:"<<h3<<"  h4:"<<h4<<endl;

}

void printB(B a){

    cout<<"B:"<<a.c1<<","<<a.i<<","<<a.c2<<","<<a.s1<<","<<a.c2<<","<<a.c3<<endl;
    int h1 = 0x000000ff & a.i;
    int h2 = 0x000000ff & (a.i >>8);
    int h3 = 0x000000ff & (a.i >>16);
    int h4 = 0x000000ff & (a.i >>24);
    cout<<"h1:"<<h1<<" h2:"<<h2<<" h3:"<<h3<<"  h4:"<<h4<<endl;

}

int main(int argc, char *argv[])
{

    cout<<"sizeof(A)"<<sizeof(A)<<endl;
    cout<<"sizeof(B)"<<sizeof(B)<<endl;

    //26 letter characters
    char buff[26] = {0};
    for(int i=0;i<26;i++)
        buff[i] = 97+i;//The value of character a is 97

    A a = {0};
    memcpy(&a,buff,sizeof(A));
    printA(a);
    B b = {0};
    memcpy(&b,buff,sizeof(B));
    printB(b);


}

Program printing

The print result is consistent with the theory (the memory distribution in the figure below)

Suppose the structure weight contains the structure, how to allocate the memory? It is worth mentioning that the memory alignment value is not the length of the structure, but the maximum length of the member types inside the structure. You can understand that the alignment value compares the memory length of the basic type (char,short,int,long,double,float, etc.). The memory alignment value in the following figure is not sizeof(B), It is the length of memory occupied by type int in structure B.
So why is the starting position of B here "105" instead of "102"?
Still compare the rules. Rule 2 stipulates that the offset of each member is an integer multiple of the memory alignment value, and structure B is the member of D. therefore, the starting position of B is a multiple of 4 from the starting position of structure D, so the starting position of B is "105"

Topics: C++