减去不可分割的指针地址

时间:2016-03-16 08:55:59

标签: 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);

Ideone link

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

2 个答案:

答案 0 :(得分:21)

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

  

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

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

答案 1 :(得分:19)

在某些假设 1 下,在C中第三行:

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

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

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

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

3 (引自:ISO / IEC 9899:201x 6.2.8物体对齐4.)
一切都有效 对齐值应为2的非负整数幂。