非数组类型的指针算术

时间:2016-01-19 14:51:28

标签: c++ language-lawyer type-punning char-pointer

让我们考虑以下代码:

struct Blob {
    double x, y, z;
} blob;

char* s = reinterpret_cast<char*>(&blob);
s[2] = 'A';

假设sizeof(double)为8,此代码是否会触发未定义的行为?

2 个答案:

答案 0 :(得分:5)

引自N4140(大致是C ++ 14):

  

3.9类型[basic.types]

     

2对于普通可复制类型T的任何对象(基类子对象除外),无论对象是否包含类型T的有效值,基础字节(1.7)都会生成可以将对象复制到charunsigned char的数组中。 42 如果复制了charunsigned char数组的内容回到物体后,物体应随后保持其原始值。

     

42)例如,使用库函数(17.6.1.2)std::memcpystd::memmove

     

3对于任何简单的可复制类型T,如果指向T的两个指针指向不同的T个对象obj1obj2,则obj1如果复制构成obj2的基础字节(1.7),则{} {} {}为基类子对象   进入obj1 43 obj2随后应保持与obj2相同的值。 [示例: ...]

     

43)例如,使用库函数(17.6.1.2)obj1std::memcpy

原则上,如果您认为间接要求将std::memmove的分配等同于将所有其他s[2]复制到一个s[2],则允许直接分配到Blob。除了第三个字节之外,恰好是字节相同的数组,并将其复制到Blob:你没有分配给s[0]s[1]等。用于简单的可复制类型包括char,相当于将它们设置为已有的确切值,这也没有可观察到的效果。

但是,如果获取s[2] == 'A'的唯一方法是通过内存操作,那么也可以使用有效的参数将您复制回Blob 的内容isn&# 39; t 构成任何先前Blob的基础字节。在这种情况下,从技术上讲,行为将因遗漏而不明确。

我强烈怀疑,特别是考虑到&#34;对象是否包含T&#34类型的有效值;评论,它是打算被允许的。

答案 1 :(得分:0)

该标准的第3.10章似乎允许该特定情况,假设&#34;访问存储的值&#34;意思是&#34;读或写&#34;,这是不清楚的。

  

3.10-10

     

如果程序试图通过访问对象的存储值   行为是除以下类型之一以外的glvalue   理解过程科幻奈德

     

- (10.1)对象的动态类型

     

- (10.2)对象的动态类型的cv-quali fi ed版本,

     

- (10.3)与动态类型类似的类型(如4.4中所定义)   对象,

     

- (10.4)对应的有符号或无符号类型的类型   对象的动态类型,

     

- (10.5)对应于a的有符号或无符号类型的类型   cv-quali fi ed版本的对象的动态类型,

     

- (10.6)包含其中一个的聚合或联合类型   上述类型的元素或非静态数据成员   (递归地,包括a的元素或非静态数据成员)   subaggregate或contains union),

     

- (10.7)一种类型,它是(可能是cv-quali fi ed)的基类类型   对象的动态类型,

     

- (10.8) char或unsigned char类型