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);