非数组类型的指针算术 [英] Pointer arithmetics on non-array types

查看:164
本文介绍了非数组类型的指针算术的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

让我们考虑下面的代码:

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

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

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

解决方案

从N4140(大致为C ++ 14)引用:


3.9类型[basic.types]



2对于任何可以复制类型的对象(基类子对象除外) code> T ,无论对象是否保存类型 T 的有效值,组成对象的底层字节可以复制到 char unsigned char 的数组。 42 char unsigned char 的数组复制回对象,对象将随后保持其原始值。 / p>

42)通过使用例如库函数(17.6.1.2) std :: memcpy std :: memmove



3对于任何简单可复制类型 T ,如果指向 T 的两个指针指向 T 对象 obj1 obj2 ,其中 obj1 obj2 如果组成 obj1 的底层字节(1.7)被复制到 obj2 43 obj2 将随后保持与 obj1 相同的值。 [示例: ...]



43)通过使用例如库函数(17.6.1.2) std :: memcpy std :: memmove



$ b b

这原则上允许直接赋值给 s [2] ,如果你采取赋值给 s [2] / code>间接地需要等效于将所有其他一些 Blob 复制到只是恰好相同的数组,除了第三个字节,并且复制它进入你的 Blob :你没有分配到 s [0] s [ 1] 等。对于包括 char 的简单可复制类型,这相当于将它们设置为它们已经具有的确切值,



但是,如果获取 s [2] =='A'的唯一方法是内存操作,那么一个有效的参数也可以做,你复制回 Blob 不是组成的底层字节任何先前的 Blob 。在这种情况下,技术上,行为将是未定义的遗漏。



我强烈怀疑,特别是考虑到对象是否保存有效的类型 T ,即表示允许。


Let's consider following piece of code:

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

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

Assuming that sizeof(double) is 8, does this code trigger undefined behaviour?

解决方案

Quoting from N4140 (roughly C++14):

3.9 Types [basic.types]

2 For any object (other than a base-class subobject) of trivially copyable type T, whether or not the object holds a valid value of type T, the underlying bytes (1.7) making up the object can be copied into an array of char or unsigned char.42 If the content of the array of char or unsigned char is copied back into the object, the object shall subsequently hold its original value.

42) By using, for example, the library functions (17.6.1.2) std::memcpy or std::memmove.

3 For any trivially copyable type T, if two pointers to T point to distinct T objects obj1 and obj2, where neither obj1 nor obj2 is a base-class subobject, if the underlying bytes (1.7) making up obj1 are copied into obj2,43 obj2 shall subsequently hold the same value as obj1. [ Example: ... ]

43) By using, for example, the library functions (17.6.1.2) std::memcpy or std::memmove.

This does, in principle, allow assignment directly to s[2] if you take the position that assignment to s[2] is indirectly required to be equivalent to copying all of some other Blob into an array that just happens to be bytewise identical except for the third byte, and copying it into your Blob: you're not assigning to s[0], s[1], etc. For trivially copyable types including char, that is equivalent to setting them to the exact value they already have, which also has no observable effect.

However, if the only way to get s[2] == 'A' is by memory manipulation, then a valid argument could also be made that what you're copying back into your Blob isn't the underlying bytes that made up any previous Blob. In that case, technically, the behaviour would be undefined by omission.

I do strongly suspect, especially given the "whether or not the object holds a valid value of type T" comment, that it's intended to be allowed.

这篇关于非数组类型的指针算术的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆