编译器是不是允许修改填充字节

Posted

技术标签:

【中文标题】编译器是不是允许修改填充字节【英文标题】:Is the compiler allowed to modify padding bytes编译器是否允许修改填充字节 【发布时间】:2022-01-14 10:48:56 【问题描述】:

假设我有一个这样的代码 sn-p(并假设我在评论中说插入了填充):

#include "stdint.h"

struct A

    uint8_t x;
    // 3 bytes of padding
    uint32_t y;
;


void foo(struct A* a)

    a->x = 0;

是否允许编译器清除填充字节或对函数 foo 中的填充字节做任何事情?

https://en.cppreference.com/w/c/language/object 对此问题保持沉默,这让我相信是的,允许编译器执行此操作....

我想知道是否允许编译器这样做的原因是我想memcmp 两个结构,我想知道我可以假设什么......

【问题讨论】:

你为什么不直接明确声明填充? @RobertHarvey 这是一个解决方案,但如果我不需要,我不一定想这样做 您可以假设,编译器实现可以随意添加填充字节,并且字节数量可能因版本而异,这称为 ABI 更改。一般来说,您根本不应该使用 memcpy 来复制结构,因为您应该使用默认生成的复制构造函数。在内部,编译器通常会为较大的结构生成一个 memcpy,以便在需要时复制和调用构造函数。如果只使用 POD,则不需要构造函数调用。与其维护对构造函数/析构函数的需求,不如让编译器单独完成它的工作! 显式声明填充有一些好处。追随你的程序员不会有你刚才提出的同样问题。 @RobertHarvey 但是你不能便携。 【参考方案1】:

是的。 C 2018 6.2.6.1 6 说:

当一个值存储在结构或联合类型的对象中时,包括在成员对象中,对应于任何填充字节的对象表示的字节采用未指定的值......

【讨论】:

它是否适用于(嗯,听起来像......)从一个 struct 对象到另一个 memcpy-ing?就像memcmp 跟随memcpy 可以产生非零结果吗? @EugeneSh.:我认为紧跟在memcpy 之后的memcmp 必须表示相等。 @EricPostpischil 你确定吗?尽管“未指定”意味着编译器供应商可以选择要放入填充的内容,但他们可能会选择不覆盖填充字节,因此它们可能包含垃圾。 (当然memcpy 会复制垃圾,所以memcmp 是对的)

以上是关于编译器是不是允许修改填充字节的主要内容,如果未能解决你的问题,请参考以下文章

用户代码可以安全地使用结构填充吗?

64位机器上的结构填充

66.javac 编译与 JIT 编译编译过程javac 编译词法语法分析填充符号表语义分析字节码生成JIT 编译

结构体变量字节填充

内在/字节码注释安全

Firebase App Check 是不是允许编译版本的 apk 文件?