【问题标题】:Preprocessor directive #pragma pack in C [duplicate]C中的预处理器指令#pragma pack [重复]
【发布时间】:2018-01-29 21:03:09
【问题描述】:

我正在尝试了解#pragma 的使用,尤其是#pragma pack() 指令。当我将 pragma pack 设置为 4.5、-5、6 等时,它是如何工作的。

【问题讨论】:

  • 你会知道,一旦你需要它,真的。没有必要仅仅为了理论而搞砸。
  • 知道所有#pragma 都是特定于实现的可能很有用。所以一旦你发现了(我同意 Eugene 不要太早尝试),下一个编译器的答案实际上可能会有所不同。这也可能导致您的特殊情况的答案:阅读您的编译器规范/文档。
  • 这在几十个网页上都有很好的解释。一个例子:stackoverflow.com/a/3318475/7673414。正如@Yunnosch 所建议的那样,极端情况下的行为可能会有所不同,因此您应该从特定编译器中查找引用。
  • 您是一位经验丰富的 C 程序员吗?如果不保留 #pragmas attribute 和其他编译器特定的高级功能
  • 好奇心有那么糟糕吗?理解这一点很可能有助于更好地理解计算机的一般工作原理

标签: c c-preprocessor pragma


【解决方案1】:

一般来说,#pragma pack 的目的是通过控制其成员的最大对齐来控制 c 中结构的大小和布局。

请参阅the GCC Docs 以了解其对语法的完整描述

我首先要关注对齐是什么。当程序对对齐没有要求时,结构的成员可能与基地址有任何偏移。当对齐时,例如 4,所有成员的偏移量必须是 4 的倍数。

#pragma pack(4)最大对齐设置为 4,而不是最小或精确对齐。我不知道强制最小对齐的方法

这是一个查看对齐效果的示例(在我的机器上默认对齐为 4)

#include <stdio.h>
#include <stddef.h>

typedef struct { 
    char  a; 
    char  b;
    long  c;
    short d;
    long  e;
} foo;

#pragma pack(push,2) //This saves the previous alignment, then lowers the maximum alignment from 4 to 2, so it will smaller (or the same size)
typedef struct {
    char  a;
    char  b;
    long  c;
    short d;
    long  e;
} bar;
#pragma pack(pop) //This reinstates the previous alignment

int main() {
    printf("a:%d b:%d c:%d d:%d e:%d\n", offsetof(foo, a), offsetof(foo, b), offsetof(foo, c), offsetof(foo, d), offsetof(foo, e));
    printf("a:%d b:%d c:%d d:%d e:%d\n", offsetof(bar, a), offsetof(bar, b), offsetof(bar, c), offsetof(bar, d), offsetof(bar, e));
}

这给出了输出

a:0 b:1 c:4 d:8 e:12
a:0 b:1 c:2 d:6 e:8

至于您的问题,如果您使用 #pragma pack(n) 会产生什么影响,其中 n 是 4.5、-1、6 等。这些都不是真正的有效值。根据文档,

下面的 n 值总是要求是 2 的小幂,并以字节为单位指定新的对齐方式

所以只有像 2、4 或 8 这样的值才有效。即使您可以使用任何整数(小数和负数没有意义),这也是不明智的。这是因为对齐两个边界的幂会加快内存访问速度。

推送和弹出功能用于保存对齐,以便您可以随意弄乱它们并在以后恢复它们

【讨论】:

  • 当我使用这些数字时,结构的大小如何?它应该与没有这些数字相同,但在某些情况下并不完全相同。
  • these kinds of numbers 指的是什么?通常,将包装设置为较小的数字可以使结构更小,但通常无论如何它都会保持相同的大小。
猜你喜欢
  • 2017-09-27
  • 1970-01-01
  • 2018-05-30
  • 2023-03-05
  • 1970-01-01
  • 1970-01-01
  • 2015-09-11
  • 1970-01-01
相关资源
最近更新 更多