关于ptrdiff_t类型指针相减返回值异常的技术咨询
嘿,这个问题问到点子上了,我给你拆解清楚这两个疑惑:
第一个问题:为什么i > j时ptrdiff_t返回正常差值,i < j时返回“无关大数”?
首先得明确:ptrdiff_t是C/C++标准规定的有符号整数类型,专门用来存储指针减法的结果。你看到的“无关大数”其实不是乱码,是有符号数的补码表示在无符号打印时的假象。
举个32位系统的例子:假设指针i的地址是0x1004,j的地址是0x1000,i > j时,i - j的结果是4,用%td(ptrdiff_t的格式化符)打印就是正常的4。但如果反过来,i是0x1000,j是0x1004,i - j的数值是-4,作为32位有符号数,它的补码是0xFFFFFFFC——如果你不小心用了无符号的格式化符(比如%u)去打印,这个值就会被解读成4294967292,看起来就是个“无关的大数”。
另外还要敲个警钟:只有当两个指针指向同一个数组的元素(或者数组末尾的下一个合法位置)时,指针减法才是有定义的行为。如果指针指向的是完全无关的变量,那这个操作本身就是未定义行为,结果可能更混乱,甚至触发程序崩溃。
第二个问题:为什么i=&a; j=&b时,得不到预期的地址数值差?
这里的核心误解是:指针减法的结果不是两个地址的数值差,而是它们之间相隔的元素个数。
举个实际的例子:假设a和b是int类型(占4字节),&a是0x1000,&b是0x1013(十进制的26)。如果a和b不在同一个数组里,那i-j本身就是未定义行为,结果完全随机。就算它们在同一个数组里,比如int arr[10]; i=&arr[5], j=&arr[2];,那i-j的结果是3(元素个数差),而不是地址数值差12(54 - 24)——指针减法会自动除以sizeof(int),得到的是元素个数,不是 raw 的地址差。
如果你确实想要两个地址的数值差,别直接用指针减法,应该把指针转换成uintptr_t(专门用来存储指针数值的无符号整数类型)再做减法,比如:
uintptr_t diff = (uintptr_t)i - (uintptr_t)j;
这样得到的就是你预期的地址数值差了。
内容的提问来源于stack exchange,提问作者coderredoc

