%u
用于无符号数字
如果我使用%d
代替%u
来显示变量的地址,我会得到相同的结果
我们仅将%u
用于道德规范,或者它也会产生任何真正的差异
看看:
int i=5;
printf("Address of i: %d", &i);
与:
相同printf("Again, address: %u" ,&i);
[编辑]将会赞赏它产生不同输出的例子。
答案 0 :(得分:7)
你可以在不经过多次往返的情况下过马路,也可能不会受到汽车撞击。这并不意味着这是一个好主意。
答案 1 :(得分:3)
%d
将为具有最高位设置(高地址)的地址显示负值%u
将始终显示位%p
是最好的,因为它明确保留用于打印地址。考虑这一点,假设地址为0xffffffff
。
#include <stdio.h>
int main () {
void* val = 0xffffffff;
printf("d = %d\n", val);
printf("u = %u\n", val);
printf("p = %p\n", val);
return 0;
}
并且,它是输出:
d = -1
u = 4294967295
p = 0xffffffff
答案 2 :(得分:2)
实际上,即使"%u"
也是错的;对于指针,您必须使用"%p"
仍然,%d
- 取而代之的是%u
,因为在您的架构上签名和无符号数字具有相同的表示,因为我们正在查看正数。因此,如果您将指针传递给%d
,printf
将尝试将参数解释为有符号整数,只要高位,您将得到%u
的相同结果未设置指针(通常是用户模式指针的标准);否则,您将获得%d
的负数和带%u
的正数(假设您的机器使用2的补码算术)。
有趣的是,最大的错误不是匹配签名,而是使用整数指定符(%d
和%u
)而不是指针指定符(%p
);实际上,大多数64位架构int
是32位,但void *
是64位,因此使用%u
代替%p
只会打印一半的地址(小端架构的下半部分,如x86_64)。
注意:所有这些解释都来自C语言的“典型实现”;就标准而言,如果您不匹配格式指定符的类型和实际数据,则会进入“未定义的行为”(=从崩溃到粉红色独角兽飞出打印机的任何内容)。
答案 3 :(得分:2)
在C中打印指针时,您应该使用%p
,而不是%u
或%d
。 %u
和%d
旨在显示整数值。当您使用这些标志打印出指针时,您隐式地将指针转换为整数,并且有很多架构会导致很多麻烦(特别是在64位架构中)。
%d
和%u
之间的区别与您提到的不同,%u
将值视为无符号,%d
视为已签名。如果最高位为1,结果将不同。使用-1时,您可以轻松看到这一点。
printf("%d, %u\n", -1, -1);
输出:
-1,4294967295
答案 4 :(得分:0)
存在不寻常的CPU架构,其中指针具有与无符号数字不同的表示或大小。
一个常见示例是以分段模式写入的32位x86代码,其中地址由具有32位段偏移的16位段号组成。 (免责声明:我看了这几年已经好几年了,所以我可能忘记了细节。)
另一种情况是64位机器设置为使用64位指针和32位整数。