Skip to content

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*))。