在C编程语言中我使用32位系统, 我有一个结构,这个结构大小是四的倍数。 但我看看Linker Map文件,大小是8的倍数 实施例
typedef struct _str
{
U64 var1,
U32 var2
} STR;
此结构的大小为16。 但是
typedef struct _str
{
U32 var1,
U32 var2,
U32 var3
} STR2;
STR2的大小为12。 我正在研究32位ARM微控制器。 我不知道为什么
答案 0 :(得分:3)
填充第一个结构以使其在U64边界上对齐:它等同于
struct STR
{
U64 var1;
U32 var2;
U8 pad[4]; /* sizeof(U64) - sizeof(U32) */
};
因此,当在结构STR []数组中使用时,每个U64都与ABI要求完全一致。
查看Procedure Call Standard for ARM Architecture,4.1基本数据类型。
答案 1 :(得分:1)
填充。
假设你有
typedef struct _str
{
U64 var1,
U32 var2
} STR;
STR s[2];
您的架构可能会要求s[0].var1
和s[1].var1
位于U64
的自然对齐位置,位于8字节边界。由于C不在数组元素之间放置填充,因此填充进入结构内部。
另一方面,
typedef struct _str
{
U32 var1,
U32 var2,
U32 var3
} STR2;
STR2 s2[2];
此处仅需要4字节对齐。
答案 2 :(得分:1)
结构的大小定义为具有最大对齐要求的成员的对齐的倍数。看起来U64的对齐要求即使在您平台上的32位模式下也是8字节。
以下代码:
#include <stdio.h>
#include <stdint.h>
int main() { printf("alignof(uint64_t) is %zu\n", __alignof(uint64_t)); }
在Linux x86_64上以32位和64位模式编译时生成相同的输出:
alignof(uint64_t) is 8
答案 3 :(得分:1)
一些背景知识,可以帮助您解决此类问题。
由于原始内存操作通常以8的倍数指定,编译器工程师决定内存数据结构的填充方案。
如果内存检索操作(内存 - >总线 - > cpu)将是16位(在假想的计算机上)块并且在结构中放置3 * 8位类型,编译器设计者可能会以及从2,16位内存填充32位结构,将进行检索操作以将结构拉入CPU缓存以进行CPU操作。
当然,您可以告诉编译器不要在异常情况下执行此操作,例如设计磁盘或网络协议,您可能希望空间有用。
在现实世界中,这些问题更为复杂,但决策源于通用有效使用硬件的最佳选择:D