%u
用于无符号数。
如果我使用%d
而不是%u
显示变量的地址,我会得到相同的结果。
我们%u
只是为了道德而使用,还是它也有任何真正的区别。
看一看:
int i=5;
printf("Address of i: %d", &i);
等同于:
printf("Again, address: %u" ,&i);
[编辑] 一个它产生不同输出的例子将不胜感激。
你可以过马路而不必多次看两边,而且你可能不会被车撞到。这并不意味着这是一个好主意。
%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
实际上,甚至"%u"
是错误的;对于您必须使用的指针"%p"
尽管如此,%d
-instead-of-仍然%u
有效,因为在您的架构中,有符号数和无符号数在我们查看正数时具有相同的表示形式。因此,如果您将指针传递给%d
,printf
将尝试将参数解释为有符号整数,并且%u
只要未设置指针的高位(这通常是用户的规范) ,您就会得到相同的结果-模式指针);否则,您将得到一个负数%d
和一个正数%u
(假设您的机器使用 2 的补码算法)。
有趣的是,最大的错误不是符号不匹配,而是使用整数说明符(%d
和%u
)而不是指针说明符(%p
);事实上,在大多数 64 位架构int
上是 32 位,但是void *
是 64 位,因此使用%u
而不是%p
只会打印地址的一半(小端架构上的下半部分,如 x86_64)。
注意:所有这些解释都来自C语言的“典型实现”;就标准而言,如果您不匹配格式说明符的类型和实际数据的类型,您将进入“未定义行为”(=从崩溃到粉红色独角兽飞出打印机的任何事情)。
在 C 中打印指针时,您应该使用%p
, not%u
或%d
. %u
并%d
旨在显示整数值。当您使用这些标志打印出指针时,您将指针隐式转换为整数,并且有很多架构会导致很多麻烦(尤其是在 64 位架构中)。
%d
和之间的区别%u
就像您提到的那样,%u
将值视为无符号和%d
有符号。如果最高位为 1,则结果会有所不同。使用 -1 时可以轻松看到这一点。
printf("%d, %u\n", -1, -1);
输出:
-1,4294967295
有一些不寻常的 CPU 体系结构,其中指针具有与无符号数不同的表示或大小。
一个常见的例子是以分段模式编写的 32 位 x86 代码,其中地址由 16 位段号和 32 位段偏移量组成。(免责声明:我看过这个已经好几年了,所以我可能已经忘记了细节。)
另一种情况是 64 位机器设置为使用 64 位指针和 32 位整数。