b - a
是一个ptrdiff_t
,你可以用%td
你的printf
格式打印.从规范部分6.5.6 添加运算符:
当减去两个指针时,两个指针都指向同一个数组对象的元素,或者指向数组对象的最后一个元素的元素; 结果是两个数组元素的下标的差异.结果的大小是实现定义的,其类型(有符号整数类型)
ptrdiff_t
在头文件中定义.
有关printf
及相关功能,请参见7.19.6 格式化输入/输出功能:
t
用于指定后续的d
,i
,o
,u
,x
,或X
转换说明适用于ptrdiff_t
或相应的无符号整数类型参数; 或者以下n
转换说明符适用于指向ptrdiff_t
参数的指针.
我在规范中捅了一些,似乎表明两个指针的差异甚至可能不适合a ptrdiff_t
,在这种情况下行为是未定义的:
J.2未定义的行为
- 减去两个指针的结果在类型ptrdiff_t
(6.5.6)的对象中不可表示.
虽然我无法想象可能出现的任何实施.我想你可以检查PTRDIFF_MIN
,并PTRDIFF_MAX
在
以十分肯定.
b - a
是一个ptrdiff_t
,你可以用%td
你的printf
格式打印.从规范部分6.5.6 添加运算符:
当减去两个指针时,两个指针都指向同一个数组对象的元素,或者指向数组对象的最后一个元素的元素; 结果是两个数组元素的下标的差异.结果的大小是实现定义的,其类型(有符号整数类型)
ptrdiff_t
在头文件中定义.
有关printf
及相关功能,请参见7.19.6 格式化输入/输出功能:
t
用于指定后续的d
,i
,o
,u
,x
,或X
转换说明适用于ptrdiff_t
或相应的无符号整数类型参数; 或者以下n
转换说明符适用于指向ptrdiff_t
参数的指针.
我在规范中捅了一些,似乎表明两个指针的差异甚至可能不适合a ptrdiff_t
,在这种情况下行为是未定义的:
J.2未定义的行为
- 减去两个指针的结果在类型ptrdiff_t
(6.5.6)的对象中不可表示.
虽然我无法想象可能出现的任何实施.我想你可以检查PTRDIFF_MIN
,并PTRDIFF_MAX
在
以十分肯定.
的结果b - a
只被定义当两个a
和b
指向相同字符数组的元素.此要求也可以解释为a
并b
指向属于同一对象的字节,因为每个对象都可以重新解释为char数组.
否则,结果是未定义的.即尝试减去这样的指针会导致未定义的行为.
定义结果时,它具有ptrdiff_t
类型.ptrdiff_t
是一个typedef名称,隐藏在该typedef名称后面的类型是实现定义的.已知该类型已签名.
另请注意,ptrdiff_t
即使指针指向同一数组的元素,C语言也不能保证足够大以容纳任何减法的结果.如果指针距离太远而ptrdiff_t
无法容纳结果,则行为未定义.
即使在C99中也没有特定的printf
格式说明符ptrdiff_t
,因此您可能最好将其转换为足够大的有符号整数类型并使用该类型的格式说明符
printf("%ld\n", (long) (b - a));
更正: C99确实有一个长度修改器ptrdiff_t
.在C99中打印结果的正确方法是
printf("%td\n", b - a);
请注意,这t
是一个长度修饰符.它可以结合d
,o
,u
,x
或X
转换符,这取决于你想获得什么样的输出格式.在C89/90中,您仍然需要坚持使用足够大的签名类型.
PS你说你无法想象它在32位或64位机器上失败了.事实上,很容易想象(或实际制造它)失败.你看到ptrdiff_t
32位机器通常是32位类型.由于它是有符号类型,因此它只有31位可用于表示值的大小.如果你选择两个相距较远的指针(即需要32位代表"距离"),结果b - a
会溢出并且没有意义.为了防止这种故障,您需要在ptrdiff_t
32位计算机上至少进行33位签名,并且在ptrdiff_t
64位计算机上至少需要65位签名.实现通常不会这样做,它们只是使用标准中的"权限"来在溢出上产生未定义的行为.
是的ptrdiff_t
.来自man stddef.h
:
ptrdiff_t Signed integer type of the result of subtracting two pointers.
打印出来%td
.