请考虑以下代码:
int* p1 = new int[100];
int* p2 = new int[100];
const ptrdiff_t ptrDiff = p1 - p2;
int* p1_42 = &(p1[42]);
int* p2_42 = p1_42 + ptrDiff;
Run Code Online (Sandbox Code Playgroud)
现在,标准保证p2_42指向p2[42]哪个?如果没有,在Windows,Linux或webassembly堆上总是如此吗?
[basic.compound]
如果两个对象是指针可互换的,那么它们具有相同的地址
然后注意到
数组对象及其第一个元素不是指针可互换的,即使它们具有相同的地址
使数组对象及其第一个元素非指针可互换的基本原理是什么?更一般地说,区分指针 - 可互换性概念与具有相同地址的概念的理由是什么?在那里某处不存在矛盾吗?
看来,给定这一系列陈述
int a[10];
void* p1 = static_cast<void*>(&a[0]);
void* p2 = static_cast<void*>(&a);
int* i1 = static_cast<int*>(p1);
int* i2 = static_cast<int*>(p2);
Run Code Online (Sandbox Code Playgroud)
p1 == p2但是,我们已经i1明确定义并且使用i2会导致UB.
根据C ++草案expr.add,当您减去相同类型但不属于同一数组的指针时,其行为是不确定的(强调是我的):
当两个指针表达式P和Q相减时,结果的类型为实现定义的有符号整数类型;此类型应与在标头([support.types])中定义为std :: ptrdiff_t的类型相同。
- 如果P和Q都得出空指针值,则结果为0。(5.2)
否则,如果P和Q分别指向同一数组对象x的元素x [i]和x [j],则表达式P-Q具有值i?j。
否则,行为是不确定的。 [?注意:如果值i?j不在std :: ptrdiff_t类型的可表示值的范围内,则行为是不确定的。-?尾注?]
将此类行为设为未定义(而不是由实现定义)的原理是什么?
放置new的返回值与其操作数的转换值之间是否存在(语义)差异?
struct Foo { ... };
char buffer[...];
Foo *a = new(buffer) Foo;
Foo *b = reinterpret_cast<Foo *>(buffer);
Run Code Online (Sandbox Code Playgroud)
是否a和b以某种方式有什么不同?
编辑:根据DaBler的评论,这个问题告诉我,如果使用const/reference成员则存在差异:使用const成员放置新类和赋值
所以,我的小位的更新问题:是否a和b以任何方式不同,如果Foo没有const或引用成员?
c++ strict-aliasing placement-new language-lawyer reinterpret-cast
2个问题:
以下代码是否已根据定义的行为很好地形成?
是否有任何可能的c ++实现可以断言?
代码(c ++ 11及更高版本):
#include <cassert>
#include <utility>
#include <ciso646>
template<class T>
auto to_address(T* p) { return reinterpret_cast<unsigned char const*>(p); }
/// Test whether part is a sub-object of object
template<class Object, class Part>
bool is_within_object(Object& object, Part& part)
{
auto first = to_address(std::addressof(object)),
last = first + sizeof(Object);
auto p = to_address(std::addressof(part));
return (first <= p) and (p < last);
}
struct X
{
int a = 0;
int& get_a() { return a; }
int& get_b() …Run Code Online (Sandbox Code Playgroud) struct A {
int a;
.
.
.
int b;
} obj;
Run Code Online (Sandbox Code Playgroud)
const ptrdiff_t diff = &obj->b - &obj->a;
将diff始终包含一个常量,即使程序运行多次也不会改变?
将diff始终是积极的?
有没有办法在编译时获得这种差异?(手动计数除外)