C 使7年前的印刷品与现在的兼容
我正在读《开发的艺术》一书,有一个名为C 使7年前的印刷品与现在的兼容,c,printf,C,Printf,我正在读《开发的艺术》一书,有一个名为memory\u segments.c的程序,它向我们演示了内存段的工作原理、堆、堆栈等。但是当我试图编译程序时,似乎打印与现在的程序不兼容。我使用gcc10.2.0来编译我的C代码 #包括 #包括 int global_initialized_var=5; int main() { printf(“全局\u初始化\u变量位于地址0x%08x\n”,&global\u初始化\u变量); //…更多打印,删除只是为了缩短代码 返回0; } //警告:格式“
memory\u segments.c
的程序,它向我们演示了内存段的工作原理、堆、堆栈等。但是当我试图编译程序时,似乎打印与现在的程序不兼容。我使用gcc
10.2.0来编译我的C代码
#包括
#包括
int global_initialized_var=5;
int main()
{
printf(“全局\u初始化\u变量位于地址0x%08x\n”,&global\u初始化\u变量);
//…更多打印,删除只是为了缩短代码
返回0;
}
//警告:格式“%x”要求参数类型为“unsigned int”,但参数2的类型为“int*”
这本书的作者:
...
global_initialized_var is at address 0x080497ec
...
对于0x%08x
有什么替代方案?为什么0x%08x
不再工作了?
0x%08x的替代方案是什么
要正确打印指针值,请将%p
与void*
指针一起使用:
printf("%p\n", (void*)&global_initialized_var);
它将使用一些特定于实现的打印形式,通常与%\x
格式相同。如果要获取指针的特定数字表示形式,最好的标准方法是使用可能的最大整数类型:
printf("%#jx\n", (uintmax_t)(uintptr_t)&global_initialized_var);
但是,通常您可以/希望将指针值强制转换为整数并打印它,因为它通常仅用于临时调试目的,就像:
// Could truncate pointer value!
printf("%#llx\n", (unsigned long long)&global_initialized_var);
printf("%#lx\n", (unsigned long)&global_initialized_var);
printf("%#x\n", (unsigned)&global_initialized_var);
请注意,unsigned
至少有16位,long
至少有32位,long
至少有64位。现在的平台是64位的,指针是64位的-无论如何,在打印指针值时更喜欢最宽的可用类型,以便于携带-因此使用上面的uintmax\t
。在unix平台上,通常使用long
向指针或从指针强制转换-在64位unix上long
有64位,而在windows上有32位
为什么0x%08x不再工作
由于类型不匹配,它现在(过去)是UB
%x
需要一个未签名的<代码>&global\u initialized\u var
是一个指针
%x
打印整数值而不是指针。这是未定义的行为。要打印指针,请使用printf(“%p”,(void*)指针)代码>
转换指针时应使用的整数类型为uintpr\u t
或intptr\u t
。指针之间的差异ptrdiff\u t
要打印uintpr\u t
或intptr\u t
您需要使用PRIdPTR PRIiPTR PRIoPTR PRIuPTR PRIxPTR
printf格式。例如:
Stackoverflow不是学习编程的好地方。考虑读一本好的C书。为什么你必须使用<代码>(空白*)< /代码>?首先,&var
的类型是什么?&var
的类型是“指向var类型的指针”。例如:int*foo代码>:现在&foo
的类型是int*
(指针指向int
c)。(void*)
是%p
所必需的,因为C标准规定了这一点,但是在大多数平台上,如果省略(void*)
@Jabberwocky,您就可以逃脱了,谢谢。而最大可能的整数类型
,似乎每一个都只有8个字节,那么(uintmax_t)(uintpttr_t)
的含义是什么?每一个都只有8个字节,怎么可能是最大的整数呢?如果long
是8个字节有什么区别?uintmax\u t
和unsigned long long
之间有什么区别吗?KamilCuk,有趣的是:(uintmax\u t)和global\u initialized\u var
如果地址超出uintmax\u t
范围,则为UB<如果uintpttr\u t
不存在(可能是因为没有支持整数类型),则code>(uintpttr\u t)和global\u initialized\u var
无法编译。我认为编译失败比UB更好。你能给我推荐一本学习这些东西的好书吗?我知道你很好。
uintptr_t p = SOME_VALUE;
printf("UINTPTR_T printed as hex: %" PRIxPTR "\n", p);