【问题标题】: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 但是你不能便携。

标签: c language-lawyer padding


【解决方案1】:

是的。 C 2018 6.2.6.1 6 说:

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

【讨论】:

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