减去不可分割的指针地址

Pau*_*aul 18 c c++ pointers

是否减去C中定义的不可分割指针地址?在C++中?

这是一个例子:

void* p = malloc(64);

int* one = (int*)((char*)p);
int* two = (int*)((char*)p + 7);

printf("%x %x %d %d\n", one, two, sizeof(int), two - one);
Run Code Online (Sandbox Code Playgroud)

Ideone链接.

我得到输出8a94008 8a9400f 4 1,所以它看起来像分裂并截断余数.是否定义了行为?

das*_*ght 21

根据5.7.6,这是未定义的行为:

当减去指向同一数组对象的元素的两个指针时,结果是两个数组元素的下标的差异.[...]除非两个指针指向同一个数组对象的元素,或者指向数组对象的最后一个元素,否则行为是未定义的.

在您的代码中,指针two不指向int与指针相同的数组元素one.实际上,它并没有指向任何数组元素p,因为它指向其中一个元素的"中间"(这本身就是一个未定义的行为).

  • @dasblinkenlight:您可能知道C标准可以容纳仅仅将未对齐指针加载到寄存器中的陷阱. (7认同)
  • 这是事实,但UB第一次出现在`(int*)((char*)p + 7)`中. (4认同)

250*_*501 19

根据一些假设1,在C中第三行:

int* two = (int*)((char*)p + 7);
Run Code Online (Sandbox Code Playgroud)

已经导致未定义的行为,因为指针p没有正确对齐它引用的类型2.


1假设int类型的对齐要求高于char类型.在大多数现代架构中都是如此.由于所有对齐必须是2的幂3且值7不是,因此将该值添加到指针p不能产生具有与int类型的对齐要求一样严格的对齐的指针.

2(引用自:ISO/IEC 9899:201x 6.3.2.3指针7.)
指向对象类型的指针可以转换为指向不同对象类型的指针.如果生成的指针未针对引用的类型正确对齐,则行为未定义.

3(引用自:ISO/IEC 9899:201x 6.2.8对象的对齐4.)
每个有效对齐值应为2的非负整数幂.