对于结构体中内存对齐的简单说明

结构体内存对齐的原因:

在运行一个结构体时,编译器需要给结构体中的每个变量成员分配内存空间,如这样一个结构体中

  typedef struct A
  {
     char c1;
      int i;
      int j;
    }A;
对其内存空间分配问题进行分析,如若不进行内存对齐,它的内存空间是:

char类型变量c1占1个字节,紧接着int类型变量i与j分别占4个字节,总有9个字节,在访问时,如图1,访问次数较多;在图2中,总有12个字节空间,虽然浪费了c1后的三个字节空间,访问次数却变少,会很大程度上节省了时间,提高了效率。用一句话概括“浪费空间用来节省时间”,这就是结构对齐的主要原因。

结构体内存对齐求其大小:

首先来看这样一个结构体

typedef struct A
{
  char c1;
  int i;
}A;
int main()
{
 A sa;
 printf("%d\n",sizeof(A));
 printf("%p\n",&(sa.c1));
 printf("%p\n",&sa);
 return 0;
}

其输出结果:8和两个相同地址。

在输出c1地址和sa的地址相同,所以结构体第一个成员变量是从内存的第一个字节空间开始的,接下来要思考为什么A的空间输出大小为8了?

首先,我们先要知道结构体默认对齐数在VS中为8,在Linux为4,现在以VS举例说明:

如上图中,char类型c1占用第一个字节,为偏移量为0的第一个字节(原因在上面已经解释),int类型变量i从偏移地址为4的字节空间开始占用四个字节,为什么从偏移地址为4这一字节开始,是以类型int字节数4的整数倍的偏移量的字节空间开始占用的,而上4的字节空间没被占用,所以从4开始,(同理char类型占用空间则为1的整数倍的偏移地址开始,double从8的整数倍的偏移地址开始等等),而结构体所占的位数要是结构体成员中所占位数最长的那个数据变量的整数倍,所以在此问题中4为最长,它的整数倍为8,所以占8个字节,c1后面的三个字节与浪费,但是与i对齐。

在举一个例子:

typedef struct s1
{
 int i;
 char j;
 int a;
 double b;
}s1

看到这个程序,首先明白这个结构体所占位数为double型字节为8的整数倍,然后分析:

int i占4个字节,char j占一个字节,j后面的3个字节浪费与i对齐;然后int a占四个字节,偏移地址从8开始到11,最后double b则从偏移地址16开始到23,所以总共占用24个字节空间,int a后的偏移地址12、13、14、15字节空间为了结构体对齐浪费掉,而24个字节正好为8的整数倍,所以当输出时其输出结果为:24

这就为结构体对齐的原因及求大小的基本知识,当然,在求大小时还有许多特殊情况,如:

(1)结构体中定义数组时的解法过程;

(2)结构体中嵌套另一个结构体时的解法过程等等

这些请看下一条博客的分析,这也是第一次第一条博客,所以以上分析可能有许多瑕疵与问题,还请能够指正指正!

 

 

### C++ 结构体内存对齐规则 在C++,为了提高CPU访问速度并优化性能,编译器会对结构体的成员变量按照一定的规则进行内存对齐处理。具体来说: #### 对齐原则 - **基本单位**:每个数据类型的自然对齐值通常是其自身的大小。例如,`char` 的对齐值为1字节,`int` 通常为4字节,而 `double` 则可能为8字节。 - **最大对齐值**:整个结构体的最大对齐值等于其具有最大对齐需求的数据类型。 #### 填充机制 为了让各成员能够按上述原则存储,编译器会在必要时向相邻两个成员间插入一定数量的填充字节(padding),使得下一个成员的位置满足其对应的对齐要求[^3]。 #### 计算过程展示 考虑如下定义: ```cpp typedef struct A { char c; int i; }; ``` 这里 `c` 用1个字节,之后由于 `int` 需要四字节边界对齐,则紧跟在其后的三个位置被作为填充位;接着放置 `i` 所需四个连续空间。因此最终该结构用至少8个字节的空间[^2]。 同样的逻辑适用于更复杂的例子如: ```cpp typedef struct C { char c; // 1 byte, padding to next multiple of 4 (total=4) int i; // 4 bytes double d; // 8 bytes, requires alignment on an 8-byte boundary so add another 4 bytes as padding before this member. char c1; // 1 byte, pad with additional 7 bytes at the end because 'd' has largest alignment requirement which is 8-bytes. }; // Total size becomes 24 bytes due to these alignments and paddings added by compiler automatically. ``` 通过以上分析可以看出,即使实际有效载荷只有少量几个字节,但由于内部成员排列顺序以及各自所需的特殊对齐条件影响下,整体所的实际内存量往往会超出预期。 对于给定的具体实例,可以通过编写测试代码来验证各个结构体的确切尺寸及其布局情况。下面是一个简单示例用于说明这一点: ```cpp #include <iostream> using namespace std; // 定义一些不同的结构体 typedef struct A { char c; int i; } StructA; typedef struct B { char c; int i; double d; } StructB; typedef struct C { char c; int i; double d; char c1; } StructC; int main(void) { cout << "struct A size = " << sizeof(StructA) << endl; cout << "struct B size = " << sizeof(StructB) << endl; cout << "struct C size = " << sizeof(StructC) << endl; return 0; } ``` 此程序将输出每种结构体经过适当调整后的总长度,从而帮助理解不同情况下编译器是如何应用内存对齐策略的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值