非数组类型的指针算术
Pointer arithmetics on non-array types
让我们考虑以下代码段:
struct Blob {
double x, y, z;
} blob;
char* s = reinterpret_cast<char*>(&blob);
s[2] = 'A';
假设 sizeof(double) 是 8,此代码是否会触发未定义的行为?
N4140(大约C++14):
3.9 类型 [基本类型]
2 对于任何简单可复制类型的对象(基类子对象除外)
T
,无论该对象是否具有T
类型的有效值,构成该对象的底层字节 (1.7) 都可以复制到char
或unsigned char
数组中。42 如果char
或unsigned char
数组的内容被复制回对象中,则对象随后应保持其原始值。42)例如,通过使用库函数(17.6.1.2)
std::memcpy
或std::memmove
。3 对于任何平凡可复制的类型
T
,如果指向T
的两个指针指向不同的T
对象obj1
和obj2
,其中obj1
和obj2
都不是基类子对象,如果构成obj1
的底层字节(1.7)被复制 43obj2
obj2
随后应保持与obj1
相同的价值。[ 示例: ... ]43)例如,通过使用库函数(17.6.1.2)
std::memcpy
或std::memmove
。
原则上,这确实允许直接分配给s[2]
,如果您认为间接需要分配给s[2]
等效于将所有其他Blob
复制到一个数组中,该数组恰好在字节上相同,除了第三个字节,并将其复制到您的Blob
: 您不会分配给s[0]
、s[1]
等。对于包括 char
在内的平凡可复制类型,这相当于将它们设置为它们已经具有的确切值,这也没有可观察到的效果。
但是,如果获得s[2] == 'A'
的唯一方法是通过内存操作,那么也可以提出一个有效的论点,即您要复制回Blob
的内容不是构成任何先前Blob
的基础字节。在这种情况下,从技术上讲,行为将不因不作为而定义。
我确实强烈怀疑,特别是考虑到"对象是否具有类型 T
的有效值"注释,它旨在被允许。
标准的第3.10章似乎允许这种特定情况,假设"访问存储的值"意味着"读取或写入",这是不清楚的。
3.10-10
如果程序尝试通过以下方式访问对象的存储值不是以下类型之一的 glvalue 行为是未定义:
—(10.1) 对象的动态类型,
—(10.2) 对象的动态类型的 CV 限定版本,
—(10.3) 与 4.4 中的动态类型类似的类型(如 4.4 中所定义)对象
—(10.4) 对应于对象的动态类型,
—(10.5) 一种类型,它是对应于对象的动态类型的 CV 合格版本,
—(10.6) 包含以下之一的聚合或联合类型其元素或非静态数据成员中的上述类型(以递归方式包括子聚合或包含的并集),
—(10.7) 一种类型,它是 (可能符合 CV 条件的)基类类型对象的动态类型,
—(10.8) 字符或无符号字符类型。
- 指向指向字符数组的指针数组的指针
- 通过指向指针数组的指针访问子类的属性
- C++,指针数组,指向双链表中的条目
- 在C++中,如何初始化指向wchar_t*的指针数组(生成wchar_t**)
- C++从函数指针数组调用函数
- 关于指向指针数组的指针
- 将返回值存储在函数指针数组的指针中是如何工作的?
- 将链表转换为指针数组时出错
- C++ 对象指针数组的复制构造函数
- C++ - 循环访问指针数组会导致错误
- 删除指针数组 (C++) 中的元素
- 如何循环访问 cpp 中的函数返回的字符指针数组
- 将函数指针数组中的函数指针作为模板参数传递
- Google Or-Tools Glop:如何创建指向 const 对象的指针数组?
- 具有推导参数的模板函数指针数组变量
- 如何模板化堆栈分配的多态指针数组到接口,包括派生类型的相应点?
- C++指针数组到字符数组中的特定位置
- 如何在C++中复制指针数组的数据
- 初始化类中的指针数组,并在另一个类中检索它
- 尽管直接设置了指针数组,但仍为空