在 C 中禁用结构填充而不使用 pragma
如何在不使用 pragma 的情况下禁用 C 中的结构填充?
How can I disable structure padding in C without using pragma?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
如何在不使用 pragma 的情况下禁用 C 中的结构填充?
How can I disable structure padding in C without using pragma?
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(6)
没有标准方法可以做到这一点。该标准规定,可以根据实现自行决定进行填充。来自 C99
6.7.2.1 结构和联合说明符
,第 12 段:话虽如此,您可以尝试以下几件事。
第一个您已经打折了,使用
#pragma
尝试说服编译器不要打包。无论如何,这都是不可移植的。也不是任何其他特定于实现的方法,但您应该检查它们,因为如果您确实需要此功能,可能有必要这样做。第二种是以从大到小的顺序对字段进行排序,例如所有
long long
类型,后跟long
类型,然后是所有int
、short
和最后的char
类型。这通常会起作用,因为通常较大的类型具有更严格的对齐要求。再说一次,不便携。第三,您可以将类型定义为 char 数组并转换地址以确保没有填充。但请记住,如果变量未正确对齐,某些架构会减慢速度,而另一些架构则会严重失败(例如引发总线错误并终止进程)。
最后一个需要进一步的解释。假设您有一个结构,其字段按以下顺序排列:
使用填充,您可能最终得到以下字节:
其中
x
是填充。但是,如果您将结构定义为:
您会得到:
然后您可以执行类似的操作:
给您:
再次不幸的是,不可移植。
所有这些“解决方案”都依赖于您对编译器和底层数据类型的深入了解。
There is no standard way of doing this. The standard states that padding may be done at the discretion of the implementation. From C99
6.7.2.1 Structure and union specifiers
, paragraph 12:Having said that, there's a couple of things you can try.
The first you've already discounted, using
#pragma
to try and convince the compiler not to pack. In any case, this is not portable. Nor are any other implementation-specific ways but you should check into them as it may be necessary to do it if you really need this capability.The second is to order your fields in largest to smallest order such as all the
long long
types followed by thelong
ones, then all theint
,short
and finallychar
types. This will usually work since it's most often the larger types that have the more stringent alignment requirements. Again, not portable.Thirdly, you can define your types as
char
arrays and cast the addresses to ensure there's no padding. But keep in mind that some architectures will slow down if the variables aren't aligned properly and still others will fail miserably (such as raising a BUS error and terminating your process, for example).That last one bears some further explanation. Say you have a structure with the fields in the following order:
With padding, you may end up with the following bytes:
where
x
is the padding.However, if you define your structure as:
you get:
You can then do something like:
to give you:
Again, unfortunately, not portable.
All these "solutions" rely on you having intimate knowledge of your compiler and the underlying data types.
除了 pragma pack 之类的编译器选项之外,您不能这样做,填充是在 C 标准中的。
您始终可以尝试通过在结构的最后声明最小类型来减少填充,如下所示:
注意 对于具有 4 字节边界的实现
Other than compiler options like pragma pack, you cannot, padding is in the C Standard.
You can always attempt to reduce padding by declaring the smallest types last in the structure as in:
Note for implementations which have 4 byte boundaries
在某些架构上,如果要求处理未对齐的数据,CPU 本身会反对。为了解决这个问题,编译器可以生成多个对齐的读或写指令,移位并拆分或合并各个位。您可以合理地预期它比对齐数据处理慢 5 到 10 倍。但是,该标准并不要求编译器做好这样做的准备……考虑到性能成本,它的需求还不够。支持显式控制填充的编译器提供了自己的编译指示,因为编译指示是为非标准功能保留的。
如果必须使用未填充的数据,请考虑编写自己的访问例程。您可能想要尝试需要较少对齐的类型(例如使用 char/int8_t),但仍然有可能例如结构的大小将四舍五入为 4 的倍数,这会紧密地挫败包装结构,在这种情况下您'您需要对整个内存区域实现您自己的访问。
On some architectures, the CPU itself will object if asked to work on misaligned data. To work around this, the compiler could generate multiple aligned read or write instructions, shift and split or merge the various bits. You could reasonably expect it to be 5 or 10 times slower than aligned data handling. But, the Standard doesn't require compilers to be prepared to do that... given the performance cost, it's just not in enough demand. The compilers that support explicit control over padding provide their own pragmas precisely because pragmas are reserved for non-Standard functionality.
If you must work with unpadded data, consider writing your own access routines. You might want to experimenting with types that require less alignment (e.g. use char/int8_t), but it's still possible that e.g. the size of structs will be rounded up to multiples of 4, which would frustrate packing structures tightly, in which case you'll need to implement your own access for the entire memory region.
要么让编译器进行填充,要么告诉它不要使用 #pragma 进行填充,要么只使用一些字节(例如 char 数组),然后自己构建所有数据(移动和添加字节)。这确实效率低下,但您可以精确控制字节的布局。有时我会手动准备网络数据包,但在大多数情况下这是一个坏主意,即使它是标准的。
Either you let compiler do padding, or tell it not to do using #pragma, either you just use some bunch of bytes like a char array, and you build all your data by yourself (shifting and adding bytes). This is really inefficient but you'll exactly control the layout of the bytes. I did that sometimes preparing network packets by hand, but in most case it's a bad idea, even if it's standard.
如果您确实想要没有填充的结构:使用仅由 8 位字节组成的结构或类定义短、整型、长整型等的替换数据类型。然后使用替换数据类型组成更高级别的结构。
C++ 的运算符重载非常方便,但在 C 中使用结构而不是类也可以达到相同的效果。下面的转换和赋值实现假设 CPU 可以处理未对齐的 32 位整数,但其他实现可以适应更严格的 CPU。
这是示例代码:
If you really want structs without padding: Define replacement datatypes for short, int, long, etc., using structs or classes that are composed only of 8 bit bytes. Then compose your higher level structs using the replacement datatypes.
C++'s operator overloading is very convenient, but you could achieve the same effect in C using structs instead of classes. The below cast and assignment implementations assume the CPU can handle misaligned 32bit integers, but other implementations could accommodate stricter CPUs.
Here is sample code:
我们可以使用以下任一方法在 C 程序中禁用结构填充。
->在结构定义后面使用 __attribute__((packed)) 。例如。
->编译 C 代码时使用
-fpack-struct
标志。例如。$ gcc -fpack-struct -o tmp tmp.c
希望这有帮助。
谢谢。
We can disable structure padding in c program using any one of the following methods.
-> use
__attribute__((packed))
behind definition of structure. for eg.-> use
-fpack-struct
flag while compiling c code. for eg.$ gcc -fpack-struct -o tmp tmp.c
Hope this helps.
Thanks.