我应该使用哪种格式说明符来打印变量的地址?我对以下很多东西感到困惑。
%u-无符号整数
%x-十六进制值
%p-无效指针
哪种是打印地址的最佳格式?
最佳答案
假设您不介意不同平台之间格式的变化和变化,最简单的答案是标准%p
表示法。
C99标准(ISO / IEC 9899:1999)在§7.19.6.1¶8中表示:
p
参数应为指向void
的指针。指针的值是
在实现定义中转换为打印字符序列
方式。
(在C11中-ISO / IEC 9899:2011中-该信息位于§7.21.6.1¶8中。)
在某些平台上,它将包含前导0x
,而在其他平台上则不包括,字母可以为小写或大写,并且C标准甚至没有定义它应为十六进制输出我知道没有实现,没有实现。
是否应使用(void *)
强制转换显式转换指针尚有争议。它是明确的,通常很不错(所以这就是我的工作),标准说“参数应为void
的指针”。在大多数计算机上,您无需删除显式的强制转换。但是,在机器上,给定存储位置的char *
地址的位表示形式与同一存储位置的“其他指针”地址的位表示形式不同将很重要。这将是字寻址的机器,而不是字节寻址的机器。这些机器如今并不常见(可能不可用),但是我大学毕业后研究的第一台机器就是这样的机器(ICL Perq)。
如果您对%p
的实现定义的行为不满意,请使用C99 <inttypes.h>
和uintptr_t
代替:
printf("0x%" PRIXPTR "\n", (uintptr_t)your_pointer);
这使您可以微调表示以适合自己。我选择将十六进制数字大写,以使数字一致地具有相同的高度,从而出现
0xA1B2CDEF
开头的特征倾角,而不是像0xa1b2cdef
那样沿数字上下倾角。不过,您可以在非常广泛的范围内进行选择。当GCC可以在编译时读取格式字符串时,明确建议使用(uintptr_t)
强制转换。我认为请求演员表是正确的,尽管我敢肯定有些人会忽略警告并在大多数情况下逃避它。Kerrek在评论中要求:
我对标准的促销活动和各种各样的争论感到困惑。所有指针是否都标准提升为void *?否则,如果
int*
是两个字节,而void*
是4个字节,那么从参数中读取四个字节显然是错误的,不是吗?我对C标准说所有对象指针必须具有相同的大小感到幻想,因此
void *
和int *
不能具有不同的大小。但是,我认为C99标准的相关部分并没有那么强调(尽管我不知道我建议为true的实现实际上是false的实现):§6.2.5类型
¶26指向void的指针应与指向字符类型的指针具有相同的表示和对齐要求。39)同样,指向兼容类型的合格或不合格版本的指针也应具有相同的表示和对齐要求。所有指向结构类型的指针应具有相同的表示和对齐要求。指向联合类型的所有指针应具有相同的表示和对齐要求。指向其他类型的指针不必具有相同的表示或对齐要求。
39)相同的表示形式和对齐要求旨在表示与函数的参数,函数的返回值和并集的成员具有互换性。
(C11在第6.2.5节,第28节和脚注48中完全相同。)
因此,所有指向结构的指针都必须具有相同的大小,并且必须共享相同的对齐要求,即使指针指向的结构可能具有不同的对齐要求。工会也是如此。字符指针和空指针必须具有相同的大小和对齐要求。指向
int
的变体(即unsigned int
和signed int
)的指针必须具有相同的大小和对齐要求;对于其他类型也是如此。但是C标准没有正式说sizeof(int *) == sizeof(void *)
。哦,很适合让您检查自己的假设。C标准明确要求函数指针的大小与对象指针的大小相同。不必破坏类似DOS的系统上的不同内存模型。那里可能有16位数据指针,但有32位函数指针,反之亦然。这就是为什么C标准不要求可以将函数指针转换为对象指针,反之亦然的原因。
幸运的是(对于面向POSIX的程序员而言),POSIX进入了漏洞并且确实要求函数指针和数据指针的大小相同:
§2.12.3Pointer Types
所有功能指针类型都应与void的类型指针具有相同的表示形式。将函数指针转换为
void *
不得更改表示形式。可以使用显式强制转换将这种转换产生的void *
值转换回原始函数指针类型,而不会丢失信息。注意:
ISO C标准不需要这样做,但是为了符合POSIX要求,它是必需的。
因此,当将指针传递给可变参数函数(例如
void *
)时,为确保代码的最大可靠性,强烈建议显式转换为printf()
。在POSIX系统上,将函数指针强制转换为空指针以进行打印是安全的。在其他系统上,这样做不一定是安全的,传递void *
以外的指针而不进行强制转换也不一定安全。
关于c - 正确的格式说明符以打印指针或地址?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58578551/