问题是这样产生的: 有如下两个结构体
struct TestAlignA
{
int a;
char b;
short int c;
__int64 d;
};
struct TestAlignB
{
char c;
int a;
short int b;
__int64 d;
};
执行以下的代码:
_tprintf(_T("size of A: %d\n"), sizeof(TestAlignA));
_tprintf(_T("size of B: %d\n"), sizeof(TestAlignB));
返回的执行结果分别为: 16 与 24
如何分析这个现象呢, 实际上这个和编译器的结构的对齐方式有关. 在不进行人为干扰的情况下(使用#pragma). 结构占用的空间可以按照以下的规则进行计算.
(1) 首先, 假设结构的起始地址为 0x00000000.
(2) 第二, 每个成员变量以其自身类型占用的空间大小进行对齐, 例如 char 类型按1对齐, short int 类型按 2 对齐, int 类型按 3 对齐等等.
(3) 第三, 结构体按照其成员中对齐数最大的成员进行对齐.
这么说好像有点晕, 我们从例子出发说明这个问题.
先说 TestAlignA 结构体, 我们假设其起始地址为 0x0000 0000. 其第一个成员变量 a 为 int 类型, 因而其以4对齐. 容易知道 0x0000 0000 mod 4 = 0, 因此其占用的地址空间为 0x0000 0000 - 0x0000 0003; 下面来看第二个成员变量 b. 它的数据类型为 char 类型, 因此其以 1 对齐. 紧接上一个成员变量a的地址为 0x0000 0004, 显然有 0x0000 0004 mod 1 = 0, 因此其占用的地址空间为 0x0000 0004(?真的如此?); 同理我们分析第三个成员变量c, 其类型为short int因此其以 2 对齐, 紧接着前一个变量的地址为 0x0000 0005, 不能和 2 整除, 因此, 前一个成员变量占用的地址不是 0x0000 0004 一个字节, 而是 0x0000 0004 - 0x0000 0005 两个字节的空间. 这样才能够满足第三个变量的对齐条件. 以此类推, 第三个成员变量占用的地址空间为 0x0000 0006 - 0x0000 0007, 第四个变量占用的地址空间为 0x0000 0008 - 0x0000 000f.
最后看一下结构体的对齐方式是否正确, 结构体中, 最大的对齐方式为以8对齐. 而下一个结构体的地址为 0x0000 0010 可以被 8 整除, 因此可以确定, sizeof(TestAlignA) = 16.
同理, 我们直接给出结构体二的对齐情况, 大家不妨自己一试.
结构体 TestAlignB 的空间占用为: 第一个成员地址空间为 0x0000 0000 - 0x0000 0003第二个成员地址空间为 0x0000 0004 - 0x0000 0007; 第三个成员地址空间为 0x0000 0008 - 0x0000 000f 第四个成员的地址空间为 0x0000 0010 - 0x0000 0018. 整个结构体占用 24 字节.
当然如果我们人为干预了结构体的对齐方式, 那么得到的结果当然就不一样了. 例如, 如果我们令结构体的成员均以2对齐(添加#pragma pack(2), 则结果均为 16, 入下所示
#pragma pack(2)
struct TestAlignA
{
int a; // 0x00 - 0x03
char b; // 0x04 - 0x05
short int c; // 0x06 - 0x07
__int64 d; // 0x08 - 0x0f
};
struct TestAlignB
{
char c; // 0x00 - 0x01
int a; // 0x02 - 0x05
short int b; // 0x06 - 0x07
__int64 d; // 0x08 - 0x0f
};
文章出处:飞诺网(www.firnow.com):http://dev.firnow.com/course/3_program/c++/cppjs/2007114/83780.html
分享到:
相关推荐
在编程中,结构体对齐是指在内存布局中,编译器为了提高访问效率而遵循的一种规则,即将结构体中的各个成员按照特定的对齐方式进行排列。GCC(GNU Compiler Collection)作为广泛使用的C/C++编译器,对于结构体对齐...
### C语言结构体的大小计算方法与结构体对齐 #### 一、使用`sizeof`计算结构体的大小 在C语言中,我们通常使用`sizeof`运算符来计算结构体的大小。例如,考虑以下结构体定义: ```c struct Student { int id; ...
这是因为GCC遵循的规则是,空结构体不占用任何空间,但其它编译器可能会添加填充字节以满足对齐要求。 最后,如果结构体或类中包含虚函数,则需要额外加上虚函数表指针的空间(通常为4或8字节,取决于平台)。基类...
### 结构体对齐、typedef、结构体指针与C++引用详解 #### 一、结构体对齐 **结构体对齐**是指在结构体中的成员变量在内存中的排列方式,这种排列是为了提高CPU访问内存的速度。由于现代处理器的设计倾向于以一定的...
在编程领域,结构体对齐是一项重要的内存管理技术,它涉及到如何在计算机内存中安排数据结构,以提高访问效率和优化存储空间。`#pragma pack` 是 C 和 C++ 编译器提供的一种预处理指令,用于控制结构体成员的对齐...
以两个具体的例子来说明结构体对齐的计算过程: 例子1: ```cpp struct my_struct { char a; long double b; }; ``` 在Windows中,由于long double的对齐模数是8,所以需要填充7字节以达到8字节对齐,结构体总...
结构体对齐是编程语言中一个重要的概念,特别是在C/C++中。它是计算机科学中用于优化内存访问效率的一种策略,确保数据在内存中按照特定的规则排列,以便CPU能更高效地读取和写入数据。对齐的主要目标是减少访问时间...
### 结构体以及结构体的对齐 #### 一、结构体的概念 在C语言中,**结构体**是一种复合数据类型,它允许开发者将不同类型的数据组合在一起形成...同时,了解结构体对齐的原理对于优化内存使用和提高程序性能至关重要。
同时,结构体的总大小(即占用的内存字节数)也会被调整到最大的对齐字节数的倍数。这是因为编译器会在必要时在结构体末尾添加填充字节以满足对齐要求。 例如,考虑以下结构体: ```c struct MyStruct { char a; /...
结构体在计算机内存中的对齐方式 在 C 语言中,结构体(struct)是一种自定义数据类型,用于组合多个变量以便更方便地组织和管理数据。但是,当我们使用 sizeof 运算符来获取结构体的大小时,经常会发现结果与预期...
写在前面的话最近有被问到:结构体怎么写占用内存小?很惭愧,当时没答到点子上 ~~呜呜呜结构体占用内存计算结构体中同样的变量个数,却可能导致占用内存的大小不同。直
本文将围绕“vc结构体数组长度计算”这一主题展开讨论,具体分析VC++编译器在处理结构体内存对齐时的行为以及如何计算结构体的大小。 #### 结构体内存对齐 在C++中,结构体是一种用户自定义的数据类型,可以包含...
结构体的使用提高了程序对数据的组织能力,但随之而来的内存对齐问题,是一个影响性能和内存使用的细节问题。下面我们详细讨论结构体内存对齐的概念、原因以及如何影响结构体的总大小。 1. 内存对齐的基本概念 在...
### 类与结构体的空间分配详解 #### 引言 在C++编程中,类和结构体是两种重要的复合数据类型,它们允许开发者定义新的数据类型,包含数据成员和成员函数。对于类和结构体的空间分配机制,理解其内部运作原理对于...
共同体(Union)与结构体类似,但它只占用足以容纳最大成员的数据空间。这意味着所有成员共享同一块内存区域,改变其中一个成员的值会影响到其他成员。定义共同体的语法与结构体相似: ```c union tagname { data_...
### 结构体与内存对齐 首先,我们需了解结构体的基本概念。结构体是一种用户自定义的数据类型,它允许我们将不同类型的数据组合在一起,形成一个单一的单元。在C语言或C++等编程语言中,结构体是通过关键字`struct`...
6. **效率与空间权衡**:内存对齐虽然可能导致结构体占用更多的内存,但能提高程序执行效率,特别是在处理大规模数据时。 了解并掌握这些知识点对于编写高效且跨平台的C语言代码至关重要。通过深入理解`sizeof`和`...