UB47⚓︎
author: Xiangzhi Liu.
Definition⚓︎
The result of subtracting two pointers is not representable in an object of type ptrdiff_t(6.5.6).
Description⚓︎
两个指针类型对象的做减法,其结果若超出 ptrdiff_t 所能容纳的范围则结果是未定义的
Code⚓︎
UB47.c
#include <stdio.h>
#include <stdint.h>
int main() {
int64_t* p = (int64_t*)0;
int64_t* q = (int64_t*)0xFFFFFFFFFFFFFFFCLLU;
ptrdiff_t l = q - p; // here produces UB44 & UB47
printf("sizeof(ptrdiff_t) == %d\n", sizeof(ptrdiff_t));
#ifdef _WIN32
printf("%I64d\n", l);
#else
printf("%lld\n", l);
#endif
return 0;
}
Configurations⚓︎
gcc version 4.9.2
Target: x86_64-w64-mingw32
MSVC _MSC_VER = 1928
Target: x86_64
Behaviors⚓︎
编译通过无警告
输出(32位):
sizeof(ptrdiff_t) == 4
27864549520572415
输出(64位):
sizeof(ptrdiff_t) == 8
-1
编译通过无警告
输出(32位):
sizeof(ptrdiff_t) == 4
78807070719082495
输出(64位):
sizeof(ptrdiff_t) == 8
-1
Advice⚓︎
通常不需要考虑此类问题。
其一 ptrdiff_t
是实现定义的,但通常 sizeof(ptrdiff_t) == sizeof(void*)
。针对那些将 ptrdiff_t
的长度定义的很小的怪异编译器可以不予考虑,如拒绝使用此类编译器。
其二,如果正常使用取地址符获取地址而非将整数转换为指针则不会遇到该 UB(假设 sizeof(ptrdiff_t) == sizeof(void*))。