pragma pack与__attribute__区别

本文详细解析了C语言中结构体对齐的两种方法:使用pragmapack(n)控制成员变量对齐,以及使用__attribute__((aligned(m)))设置结构体整体对齐。通过示例代码展示了不同对齐方式对内存占用的影响。

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

一、pragma pack(n):告诉编译器结构体或类内部的成员变量相对于第一个变量的地址的偏移量的对齐方式,缺省情况下,编译器按照自然边界对齐,当变量所需的自然对齐边界比n大 时,按照n对齐


二、__attribute__((aligned(m))):告诉编译器一个结构体或者类或者联合或者一个类型的变量(对象)分配地址空间时的地址对齐方式。
也就是说,如 果将__attribute__((aligned(m)))作用于一个类型,那么该类型的变量在分配地址空间时,其存放的地址一定按照m字节对齐(m必 须是2的幂次方)。
__attribute__((aligned(m)))也可以作用于一个单独的变量。


注: pragma作用于结构内的成员变量;attribute ((aligned(n)))作用于结构体分配地址的对齐方式

__attribute__ ((__packed__))关键字,它可以做到让我们的结构体,按照紧凑排列的方式,取消编译器对齐优化。

2.1 __attribute__((aligned(m))) 与占用内存大小,见如下代码:

 

 #include<stdio.h>

 #include<stdio.h>

#pragma pack(2)

typedef struct{

char f2;

int f3;

}ST3;  //ST3各成员变量2字节对齐

#pragma pack()

//////////////////////////////////////////////////////////


typedef int more_aligned_int __attribute__((aligned(16)));//more_aligned_int 16字节对齐,sizeof=4
typedef int __attribute__((aligned(16))) more_aligned_int_1 ;//more_aligned_int__1 16字节对齐,sizeof=4....但是 more_aligned_int 代表的意思 != more_aligned_int_1

typedef struct{
	int a;
	char b;
} __attribute__((aligned(64))) ST2;//ST2起始地址64字节对齐,sizeof(ST2)=64

typedef struct{
	int a;
	char b;
} ST1 __attribute__((aligned(64)));//ST1起始地址64字节对齐,sizeof(ST1)=8,所以不能定义ST1结构体数组(数组要求地址连续)

///////////////////////////////////////////////////////////
int main()
{
	//ST1 st1[3];//error: alignment of array elements is greater than element size
	ST1 st1;	
	ST2 st2;
	ST3 st3;
	printf("sizeof st1 =%u,sizeof st2 =%u,sizeof st3=%u,sizeof int_1=%d\n",sizeof(st1),sizeof(st2),sizeof(st3),sizeof(more_aligned_int_1));//8,64,6(重新定义结构体按新方式对齐),4
	return 0;
}

 



原文:https://blog.youkuaiyun.com/minyuanxiani/article/details/82626919  
 

### 错误原因分析 VSCode 中出现 `expected '=', ',', ';', 'asm' or '__attribute__' before '#pragma'` 的错误通常是由于以下几种情况之一引起的: 1. 当前使用的编译器不支持 `#pragma pack(push, _CRT_PACKING)` 这种形式的指令。 2. 配置文件中缺少必要的头文件路径或宏定义,导致编译器无法正确解析该指令。 3. VSCode 的 IntelliSense 配置存在问题,未能正确识别所用的标准或编译选项。 --- ### 解决方法 #### 1. **确认编译器支持性** 确保当前环境中的编译器支持 `#pragma pack(push, _CRT_PACKING)` 指令。例如,MSVC 编译器完全支持这种语法,而 GCC/Clang 默认情况下可能需要额外配置才能启用类似的特性[^1]。可以通过以下命令检查编译器版本支持的 pragma 功能: ```bash gcc --version clang --version ``` 对于 GCC Clang,可以尝试使用 `-fms-extensions` 参数以启用 MSVC 兼容模式: ```bash g++ -fms-extensions your_file.cpp -o output ``` #### 2. **调整 VSCode 的 C/C++ 扩展配置** 编辑 `.vscode/c_cpp_properties.json` 文件,确保其包含正确的编译器路径标准库路径。以下是示例配置: ```json { "configurations": [ { "name": "Win32", "includePath": [ "${workspaceFolder}/**", "C:/Program Files (x86)/Microsoft Visual Studio/.../Include" ], "defines": ["_DEBUG", "UNICODE", "_UNICODE"], "compilerPath": "C:/Program Files (x86)/Microsoft Visual Studio/.../cl.exe", "cStandard": "c17", "cppStandard": "c++17", "intelliSenseMode": "windows-msvc-x64" } ] } ``` 在此配置中,`compilerPath` 应指向实际使用的 MSVC 编译器位置,以便 IntelliSense 能够正确解析 `#pragma pack` 指令[^2]。 #### 3. **验证 pragma pack 的写法** 确保代码中 `#pragma pack` 的书写符合目标编译器的要求。例如,在 MSVC 下,推荐的形式如下: ```cpp #pragma pack(push, _CRT_PACKING) struct MyStruct { char c; int i; }; #pragma pack(pop) ``` 而在 GCC 或 Clang 中,需显式启用 MSVC 兼容模式,并改写为等效的属性形式(如果必要): ```cpp __attribute__((aligned(1))) struct MyStruct { char c; int i; }; ``` #### 4. **清理构建缓存** 有时先前的构建过程可能会遗留一些无效的数据,从而干扰新代码的正常工作。建议清空项目的构建目录后再重新执行构建流程: ```bash rm -rf ./build/ mkdir build && cd build cmake .. make ``` 通过以上步骤的操作,应当能够有效解决 `#pragma pack(push, _CRT_PACKING)` 导致的相关错误。 --- ### 示例修正后的代码片段 针对不同编译器提供统一化的解决方案: ```cpp #ifdef _MSC_VER #pragma pack(push, _CRT_PACKING) #else #pragma pack(push, 1) // For GCC and Clang with -fms-extensions enabled #endif struct AlignedStruct { uint8_t byteField; uint32_t dwordField; }; #ifdef _MSC_VER #pragma pack(pop) #else #pragma pack(pop) #endif ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值