32、64位编译器各类型大小和字节对齐

本文介绍了32位和64位编译器下各种数据类型的大小,并详细解释了字节对齐原则及其在不同结构体中的应用实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

32位编译器:32位系统下指针占用4字节

      char:1个字节

      char*(即指针变量): 4个字节(32位的寻址空间是2^32, 即32个bit,也就是4个字节。同理64位编译器)

      shortint :2个字节

      int:  4个字节

      unsigned int: 4个字节

      float:  4个字节

      double:   8个字节

      long:   4个字节

      longlong:  8个字节

      unsigned long: 4个字节

64位编译器:64位系统下指针占用8字节

      char:1个字节

      char*(即指针变量): 8个字节

      shortint :2个字节

      int:  4个字节

      unsigned int: 4个字节

      float:  4个字节

      double:   8个字节

      long:   8个字节

      longlong:  8个字节

      unsigned long: 8个字节

 

字节对齐的细节和具体编译器实现相关,但一般而言,满足三个准则:

1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;

2) 结构体每个成员相对于结构体首地址的偏移量都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节;例如上面第二个结构体变量的地址空间

3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节。

4)结构体作为数据成员的对齐规则:在一个struct中包含另一个struct,内部struct应该以它的最大数据成员大小的整数倍开始存储


64位编译器:

 

Example1:

structA{   

 longa1;

 short a2

 inta3;

 int*a4;

};                 

        内存大小:sizeof(A)=8+((2+4+2+8 =24

注:括号部分填充2个字节对齐

 

Example2:

struct B

{

char a;

double b;  

int c;

};      内存大小:sizeof(B) = (1+7) + 8+ (4+4) = 24, 注:前部分填充7个字节补齐,后面填充4个字节补齐

 

Example3:

struct C

{

int a,

A b,   

char c,

};      

                            内存大小:sizeof(C) = (4+4) + 24 + (1+7) = 40, 注:前部分填充4个字节补齐,后面填充7个字节补齐


转载并归纳是学习的好方法!!!

<think>我们讨论的是如何在Green Hills编译器中设置8字节对齐。在C/C++代码中,对齐设置通常涉及以下几个方面: 1. 结构体对齐(结构体成员对齐整个结构体的对齐) 2. 栈对齐 3. 全局变量静态变量的对齐 4. 动态内存分配的对齐(例如malloc返回的内存,但这通常由运行时库控制) 在Green Hills编译器中,我们可以通过以下几种方式设置8字节对齐: ### 方法1:使用编译选项设置默认对齐 Green Hills编译器提供了`-align`选项来设置默认的对齐方式。例如: ```bash ccarm -align=8 ... # 设置8字节对齐 ``` 这个选项会影响结构体、联合体以及独立变量的对齐。但是需要注意的是,这个选项设置的是最大对齐,编译器可能会根据实际情况选择更小的对齐(例如基本类型int通常是4字节对齐,即使设置了8字节对齐,它可能还是4字节对齐,除非是double类型或显式指定对齐)。 ### 方法2:使用属性指定特定变量或结构体的对齐 在代码中,我们可以使用`__attribute__`来指定变量或类型的对齐方式。例如: ```c // 变量对齐 __attribute__((aligned(8))) int global_var; // 结构体成员对齐(整个结构体对齐) struct my_struct { char a; int b __attribute__((aligned(8))); } __attribute__((aligned(8))); // 或者使用C11标准中的_Alignas(如果编译器支持C11) #include <stdalign.h> alignas(8) int global_var2; ``` ### 方法3:设置栈对齐 在函数中,局部变量于栈上。栈对齐可以通过函数属性来设置: ```c __attribute__((force_align_arg_pointer)) // 通常用于确保栈在函数入口时对齐,但具体属性可能根据架构不同 ``` 然而,更通用的做法是在链接脚本中设置栈指针的初始值,确保栈指针是8字节对齐的。另外,编译器选项也可以控制栈对齐。 Green Hills编译器提供了`-stackalign`选项来设置栈对齐: ```bash ccarm -stackalign=8 ... ``` ### 方法4:链接脚本中的对齐设置 在链接脚本(.lsl文件)中,我们可以为段(section)设置对齐。例如: ``` SECTIONS { .data ALIGN(8): { *(.data) } .bss ALIGN(8): { *(.bss) } ... } ``` 这样,每个段的起始地址都会按照8字节对齐。 ### 方法5:动态内存分配的对齐 动态内存分配(如malloc)的对齐通常由运行时库决定。在Green Hills编译器中,可以通过重新实现`malloc`函数或使用编译器提供的对齐分配函数(如`memalign`或`aligned_alloc`)来确保对齐。 ### 总结 要全面设置8字节对齐,可能需要组合使用以上方法: 1. 使用编译选项`-align=8``-stackalign=8`来设置默认的对齐栈对齐。 2. 在代码中对关键变量结构体使用`__attribute__((aligned(8)))`。 3. 在链接脚本中设置各段的对齐。 4. 使用对齐的动态内存分配函数。 注意:具体的编译选项可能因Green Hills编译器的版本目标架构(如ARM、PowerPC等)而略有不同,请参考对应版本的编译器手册。 ### 示例:编译命令 假设我们有一个源文件`example.c`,我们可以这样编译: ```bash ccarm -align=8 -stackalign=8 -c example.c -o example.o ``` 然后链接时,在链接脚本中设置段对齐。 ### 验证对齐 编译完成后,可以使用`elxr`工具(或`objdump`)查看目标文件中的段符号的地址,确保它们都是8字节对齐的。 例如,使用Green Hills的`elxr`工具查看目标文件: ```bash elfdump -s example.o ``` 查看符号的地址,检查是否满足8字节对齐(地址低3为0)。 ### 相关问题 1. Green Hills编译器中如何为特定结构体设置16字节对齐? 2. 如何验证Green Hills编译生成的目标文件满足指定的对齐要求? 3. 在嵌入式系统中,为什么需要对齐内存访问?</think>在 Green Hills 编译器中设置 8 字节对齐,主要有以下几种方法,涵盖了编译选项、代码属性链接脚本控制: ### 一、编译选项设置全局对齐(推荐) 使用 `-align` 选项设置全局默认对齐值: ```bash ccarm -align=8 -c your_file.c -o output.o ``` * **效果**:所有变量、结构体按 8 字节对齐 * **验证**:编译后检查日志或使用 `elfdump` 工具查看段对齐属性 ### 二、代码属性设置特定对齐 在变量或结构体声明中使用 `__attribute__` 强制对齐: ```c // 单变量对齐 __attribute__((aligned(8))) volatile uint64_t sensor_data; // 结构体整体对齐 struct __attribute__((aligned(8))) SensorPacket { uint32_t timestamp; uint32_t value; uint8_t status; }; // 数组成员对齐 uint32_t buffer[128] __attribute__((aligned(8))); ``` ### 三、链接脚本控制段对齐 在 `.lsl` 文件中指定段对齐: ```ld SECTIONS { .data ALIGN(8): { /* 强制8字节对齐 */ *(.data) } > RAM .bss ALIGN(8): { /* 未初始化数据对齐 */ *(.bss) } > RAM } ``` ### 四、栈对齐设置(函数调用) 使用函数属性确保栈帧对齐: ```c __attribute__((force_align_arg_pointer)) void critical_function() { // 函数入口栈指针自动对齐到8字节边界 } ``` ### 五、动态内存对齐 使用专用对齐分配函数: ```c #include <stdlib.h> void* aligned_alloc(size_t alignment, size_t size); // 示例:分配64字节且8字节对齐的内存 uint64_t* ptr = aligned_alloc(8, 64); ``` ### 对齐验证方法 1. **编译日志检查**: ```bash ccarm -align=8 -v your_file.c # -v显示详细对齐信息 ``` 2. **目标文件分析**: ```bash elfdump -S output.o | grep -i align ``` 3. **地址验证**: ```c printf("Address: 0x%lx\n", (uintptr_t)&sensor_data); // 输出地址低3应为0 (0x...0, 0x...8) ``` ### 注意事项 1. 对齐过度可能增加内存碎片 2. 硬件限制:某些架构(如 Cortex-M0)不支持非对齐访问 3. 性能权衡:对频繁访问的数据使用对齐,对大型数组谨慎使用 4. C11 标准替代方案: ```c #include <stdalign.h> alignas(8) uint64_t counter; // C11标准语法 ``` ### 相关问题 1. 如何在 Green Hills 中为特定结构体成员设置独立对齐? 2. 当使用 `-align=8` 时,如何排除某些变量不需要强制对齐? 3. Green Hills 链接脚本中 `ALIGN()` `ALIGN_WITH_INPUT` 的区别是什么?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值