如果值没有改变,是否允许改变对象的底层字节?

时间:2017-08-23 11:59:47

标签: c++ language-lawyer

如果值本身未更改,是否允许更改对象的基础字节?

因此,例如,此代码段打印"可能会有所不同吗?

int a = 0;
char b[sizeof(int)];

memcpy(b, &a, sizeof(int));
if (memcmp(b, &a, sizeof(int)) {
    printf("differ\n");
}

以下问题让我问这个问题:Is delete allowed to modify its parameter?,请查看问题下方的评论,例如Johannes Schaub撰写的comment

  

什么规则禁止更改int的内部位?就我而言   知道,甚至允许实现使int a = 0; / *测试   ' a'现在 /; / 测试位' a'现在* /有两个不同的位   每次

1 个答案:

答案 0 :(得分:3)

通常,memcpymemcmp严格按字节工作,因此无法区分。

(C ++ 11)标准的一个阅读似乎表明可能可能int与另一个(memcmp)不同,你可以如果允许整数具有对值没有影响的填充字节,则只需从中分配它。

根据您的代码使用int和类似大小的char缓冲区似乎是可行的:

int a = 0;
char b[sizeof(int)];
memcpy(b, &a, sizeof(int));

a中的填充字节(如果有)以基础值不变的方式进行更改。 可能导致memcmp失败。

可以在C++11 3.9.1 Fundamental types

中找到特定的阅读材料
  

对于字符类型,对象表示的所有位都参与其中   在价值表示中。对于无符号字符类型,值表示的所有可能位模式表示数字。 这些要求不适用于其他类型。

这允许在非字符类型中填充位,并且标准中没有任何内容明确地防止这些位在任何时候发生变化。

然而,在同一部分中,它将字符和有符号或无符号整数混合成一个"整数类型"类别并声明:

  

整数类型的表示应使用纯二进制计算系统定义值。 (脚注49)[例子:本国际标准允许积分类型的2的补码,1的补码和带符号的幅度表示。 - 例子]

脚注49状态:

  

使用二进制数字0和1的整数的位置表示,其中由连续位表示的值是加法的,以1开始,并且乘以2的连续积分幂,除了可能具有最高位的位位置。 (改编自美国国家信息处理系统词典。)

这似乎没有为这些类型中的填充位留下开放的可能性,因为它非常具体地调用连续的位和2的幂,唯一的例外是提到的是高位(用于决定三种可能编码的符号)(a)

所以我怀疑memcmp使用相同的内存块和大小memcpy之后不能立即失败。

当然,这与您链接的问题完全无关,因为有一个介入操作delete,可以自由更改基础位模式。这种情况与以下情况没有什么不同:

int a = 0;
char b[sizeof(int)];
memcpy(b, &a, sizeof(int));
a = 42; // intervening operation

之后memcmp几乎保证将两个内存块视为不同。

(a)令人讨厌的是,一个潜在读数允许填充位,同时仍然满足"后续"上面提到的比特和2的幂 - 如果填充比特位于基础比特模式的低端(距离符号最远),则是这样。如果允许那么,是的,memcmp可以在memcpy之后立即报告差异。