POD 类型的填充字节是不是被复制?
Posted
技术标签:
【中文标题】POD 类型的填充字节是不是被复制?【英文标题】:Do the padding bytes of a POD type get copied?POD 类型的填充字节是否被复制? 【发布时间】:2018-04-03 03:44:06 【问题描述】:假设我有一个像这样的 POD 类型:
struct A
char a;
int b;
;
在我的系统上,sizeof(A) == 8
,即使 sizeof(char) == 1
和 sizeof(b) == 4
。这意味着数据结构有 3 个未使用的字节。
现在假设我们这样做
A x = ...;
A y =x;
问题:
是否保证 x
和 y
的所有 8 个字节都相同,即使是未使用的 3 个?
同样,如果我将一些 A
对象的底层字节传输到另一个不理解它们的含义或结构的程序,并将它们视为一个 8 字节的数组,那么其他程序可以安全地比较两个 A
s为了平等?
注意:In an experiment with gcc 7,这些字节似乎确实被复制了。我想知道这是否得到保证。
【问题讨论】:
相关:***.com/a/1575369/955273 我不认为骗子回答了“填充字节是否相同”的问题。它只是说 memcpy 复制它们,但这并不是 OP 所要求的。 @vsoftco "=
只需要复制成员。它可能会也可能不会复制填充。" 最佳答案中的第二段。
不保证赋值或初始化会复制填充。在某些情况下,不复制它可能很重要(填充可以在继承中重用)。 memcpy
会复制它,因为它不知道。
如果您还需要复制填充字节,您可以使用memcpy()
来完成。我有时在 C 中使用的另一种技术是使用 memset()
将结构的所有字节设置为 0,然后 然后 进行成员复制。十多年来,现代编译器已经能够优化冗余双写。
【参考方案1】:
非联合类 X 的隐式定义复制/移动构造函数执行成员方式复制/移动 其基地和成员。
N4141 中的 12.8/15 [class.copy]
因此允许填充字节中的位模式不同。
【讨论】:
不幸的是,N4141 是password protected。看起来它是 C++14 的最终标准。草稿为N4140,信息为from this Reddit thread。我不能说我 100% 信任那个 reddit 线程。其中,它是 12.8/16,而不是 15。是否有任何有向图,其中标准和草案是节点,边表示 是 的一部分? @StefanHanke 实际上,N4141 的源代码在 github 上可用,您只需要自己构建即可。 github.com/cplusplus/draft/tree/n4141 “其实N4141的源码在github上就可以找到,你自己构建就好”这话说的很C++。 这是否意味着它不能复制填充字节,或者它不需要? (我认为根据 as-if 规则可以吗?) @Borgleader 我不会从引文中读到这一点(即我认为它可以复制)。【参考方案2】:这不是权威的,但cppreference
对std::memcmp
的条目表明填充字节可能不同:
memcmp()
两个structchar c; int n;
类型的对象之间将比较当c
和n
的值相同时其值可能不同的填充字节
【讨论】:
不确定这与复制有什么关系?【参考方案3】:鉴于您询问了 POD 类型(因此包括联合),值得一提的是,根据 [class.copy]
联合 X 的隐式定义的复制/移动构造函数复制 X 的 对象表示 (6.9)
对于普通可复制类型也应该包括填充位。 因此,可能只是将 A 替换为
union A struct
char a;
int b;
; ;
(实际上,上面使用了一个非标准的匿名结构,但你明白了......)
【讨论】:
相关链接:***.com/questions/26241397/…【参考方案4】:回答你的第二个问题:
等效地,如果我将一些 A 对象的底层字节传输到另一个不了解它们的含义或结构的程序,并将它们视为一个 8 字节的数组,那么其他程序可以安全地比较两个 As 的相等性吗?
由于您的类型的对象可能包含填充字节,另一个程序通常无法比较两个这样的对象是否相等:
知道在语义上构成对象的字节中的哪些位是定义其值表示的关键。然而,在这种情况下,目标程序只知道对象表示,即在内存中表示这样一个对象的字节序列,包括填充字节。像 memcmp 这样的函数只能以有意义的方式比较其值表示与其对象表示相同的对象。如果你使用它来比较对象的值,即使它们有填充,它可能无法给出正确的结果,因为它无法判断对象表示中的哪些位与两个对象的值表示相等。
见http://en.cppreference.com/w/cpp/language/object
【讨论】:
以上是关于POD 类型的填充字节是不是被复制?的主要内容,如果未能解决你的问题,请参考以下文章
为了确保 C++ 类型是 POD,我必须遵循哪些规则? [复制]
uint8_t 类型数组的元素是不是总是被打包到内存的连续字节中?
将包含 POD 的包装器结构数组转换为它包含的 POD 类型数组是不是合法?