网站首页 > 基础教程 正文
现代主流C和C++编译器MSVC与GCC均支持使用 #pragma pack 来指定某组结构体或联合体(C++还可支持类)的每一个成员的最大对齐字节数。这在某些诸如可跨平台的对象序列化等应用场合会比较有用。下面笔者将介绍GCC与MSVC均能支持的 #pragma pack 的几种形式。
- #pragma pack( push [ , n ] ):表示先将当前pack对齐的设置保存在当前编译器栈上,然后用 n 来设置新的pack对齐要求。n是可缺省的。如果缺省,那么以当前编译器默认设置的pack对齐方式进行设置。
- #pragma pack( pop ):表示将当前pack对齐的设置推出编译器对pack对齐设置的栈,而回到前一个设置。
- #pragma pack( [ n ] ):表示用 n 来设置新的pack对齐设置。n是可缺省的。如果缺省,那么以当前编译器默认设置的pack对齐方式进行设置。
下面提供一些示例代码为大家提供一个更好的直观感受。以下代码可在Visual Studio 2019或更高版本上的MSVC(通过将C语言编译选项设置为C11或C17)以及GCC 4.8以上、Clang 3.6以上通过编译和运行。
#include <stdio.h>
#include <stdalign.h>
#pragma pack(2)
typedef struct S1
{
char c;
int i;
} S1;
#pragma pack(push, 1)
typedef struct S2
{
char c;
int i;
} S2;
typedef struct S3
{
char c;
long long ll;
} S3;
// 恢复为之前pack设置
#pragma pack(pop)
typedef struct S4
{
char c;
long long ll;
} S4;
// 恢复为当前编译器默认的pack设置
#pragma pack()
typedef struct S5
{
char c;
int i;
} S5;
int main(void)
{
// 输出:S1 size: 6, alignment: 2, c offset: 0, i offset: 2
printf("S1 size: %zu, alignment: %zu, c offset: %zu, i offset: %zu\n",
sizeof(S1), alignof(S1), offsetof(S1, c), offsetof(S1, i));
// 输出:S2 size: 5, alignment: 1, c offset: 0, i offset: 1
printf("S2 size: %zu, alignment: %zu, c offset: %zu, i offset: %zu\n",
sizeof(S2), alignof(S2), offsetof(S2, c), offsetof(S2, i));
// 输出:S3 size: 9, alignment: 1, c offset: 0, i offset: 1
printf("S3 size: %zu, alignment: %zu, c offset: %zu, i offset: %zu\n",
sizeof(S3), alignof(S3), offsetof(S3, c), offsetof(S3, ll));
// 输出:S4 size: 10, alignment: 2, c offset: 0, i offset: 2
printf("S4 size: %zu, alignment: %zu, c offset: %zu, i offset: %zu\n",
sizeof(S4), alignof(S4), offsetof(S4, c), offsetof(S4, ll));
// 输出:S5 size: 8, alignment: 4, c offset: 0, i offset: 4
printf("S5 size: %zu, alignment: %zu, c offset: %zu, i offset: %zu\n",
sizeof(S5), alignof(S5), offsetof(S5, c), offsetof(S5, i));
}
此外,为了能更方便地为单个结构体等复合类型设置每个成员最大只能以1个字节对齐的设置,GCC和Clang分别提供了扩展语法进行设置。
以下为GCC的语法扩展:
struct __attribute__((packed)) S
{
char c;
int i;
};
以下为Clang编译器所支持的语法扩展:
struct [[gnu::packed]] S
{
char c;
int i;
};
请注意,Clang的该语法扩展只能用于C++11开始起的C++编译器以及可支持C2X标准的C语言编译器。印象中,Clang 9开始应该能支持 -std=gnu2x 这一编译选项。因此如果各位在Clang上用的是C编译器的话,需要显式使用该选项。
猜你喜欢
- 2024-12-30 C++ 在编程语言谱系中的位置及其特点
- 2024-12-30 C++基础知识总结(超详细总结) c++ 基础
- 2024-12-30 [面试]C++中struct和class的区别是什么
- 2024-12-30 C++类和C语言的结构体有什么区别?linux C++第18讲
- 2024-12-30 结构体所占内存大小 结构体所占内存大小是所有成员所占的内存字节数计算
- 2024-12-30 结构体的各种使用方法详细讲解-c\c++
- 2024-12-30 C++,结构体和类,结构体和类的区别,struct与class的区别
- 2024-12-30 C++编程:复合数据类型—结构体 c语言结构体复数运算
- 2024-12-30 C#与C++交互开发系列之复杂类型传递与解析
- 2024-12-30 C#和C++混合编程开发示例 c#,c++,c
- 最近发表
- 标签列表
-
- gitpush (61)
- pythonif (68)
- location.href (57)
- tail-f (57)
- pythonifelse (59)
- deletesql (62)
- c++模板 (62)
- css3动画 (57)
- c#event (59)
- linuxgzip (68)
- 字符串连接 (73)
- nginx配置文件详解 (61)
- html标签 (69)
- c++初始化列表 (64)
- exec命令 (59)
- canvasfilltext (58)
- mysqlinnodbmyisam区别 (63)
- arraylistadd (66)
- node教程 (59)
- console.table (62)
- c++time_t (58)
- phpcookie (58)
- mysqldatesub函数 (63)
- window10java环境变量设置 (66)
- c++虚函数和纯虚函数的区别 (66)