zmb*_*mbq 16 c printf pointers
在最近的一个问题中,有人提到当使用printf打印指针值时,调用者必须将指针强制转换为void*,如下所示:
int *my_ptr = ....
printf("My pointer is: %p", (void *)my_ptr);
Run Code Online (Sandbox Code Playgroud)
对于我的生活,我无法弄清楚为什么.我发现了这个问题,几乎是一样的.问题的答案是正确的 - 它解释了整数和指针的长度不一定相同.
这是当然的,真实的,但是当我已经在的情况下有一个指针,像上面,我为什么要由铸铁int *
到void *
?什么时候int*与void*不同?事实上,什么时候(void *)my_ptr
生成任何与简单不同的机器代码my_ptr
?
更新:多个知识渊博的响应者引用了标准,说传递错误的类型可能会导致未定义的行为.怎么样?我期望printf("%p", (int *)ptr)
并printf("%p", (void *)ptr)
生成完全相同的堆栈帧.两个调用何时生成不同的堆栈帧?
oua*_*uah 20
p
转换说明符需要一个类型的参数void *
.如果未传递类型的参数void *
,则函数调用将调用未定义的行为.
从C标准:
(C11,7.21.6.1p8格式化输入/输出函数)"p参数应为指向void的指针."
C中的指针类型不需要具有相同的大小或相同的表示.
具有不同指针类型表示的实现的示例是Cray PVP,其中指针类型的表示为64位,void *
而char *
对于其他指针类型为32位.
请参阅"Cray C/C++参考手册",表3中的"9.1.2.2" http://docs.cray.com/books/004-2179-003/004-2179-003-manual.pdf
AnT*_*AnT 17
在C语言中,所有指针类型的表示可能不同.所以,是的,int *
不同于void *
.可以很难(或不可能)找到能够说明这种差异的真实平台,但在概念层面,差异仍然存在.
换句话说,通常情况下,不同的指针类型具有不同的表示.int *
不同于void *
和不同double *
.就C语言而言,您的平台使用相同的表示形式void *
并且int *
只不过是巧合.
一些指针类型都要求有相同的表述语言状态,其中包括void *
主场迎战char *
,指向不同的结构类型,或者说,int *
和const int *
.但这些只是一般规则的例外.
其他人已经充分解决了传递int *
一个原型函数的情况,该函数具有固定数量的参数,这些参数需要不同的指针类型.
printf
不是这样的功能.它是一个可变参数函数,因此默认参数升级用于其匿名参数(即格式字符串之后的所有内容),并且如果每个参数的提升类型与格式效应器所期望的类型不完全匹配,则行为未定义.特别是,即使 int *
并且void *
具有相同的表示,
int a;
printf("%p\n", &a);
Run Code Online (Sandbox Code Playgroud)
有未定义的行为.
这是因为调用帧的布局可能取决于每个参数的确切具体类型.为指针和非指针类型指定不同参数区域的ABI已经在现实生活中发生(例如,Motorola 68000希望您尽可能地在地址寄存器和数据寄存器中的非指针中保持指针).我不知道任何真实的ABI会分离不同的指针类型,但它是允许的,听到一个我也不会感到惊讶.
\n\n当使用 printf 打印指针值时,调用者必须将指针强制转换为 void *
\n
即使强制转换为void *
也不足以满足所有指针的需要。
C 有两种指针:对象指针和函数指针。
\n任何对象指针void*
都可以毫无问题地转换为:
printf("My pointer is: %p", (void *)my_ptr); // OK when my_ptr points to an object\n
Run Code Online (Sandbox Code Playgroud)\n函数指针的转换void *
未完全定义。
考虑 2021 年的系统,其中void *
64 位,函数指针为 128 位。
C 确实指定了(我的重点)
\n\n\n任何指针类型都可以转换为整数类型。除非前面指定,否则结果是实现定义的。如果结果不能以整数类型表示,则行为未定义。结果不必在任何整数类型的值范围内。C17dr \xc2\xa7 6.3.2.3 6
\n
要打印函数指针可以尝试:
\nprintf("My function pointer is: %jX", (uintmax_t) my_function_ptr); // Selectively OK\n
Run Code Online (Sandbox Code Playgroud)\nC 缺乏真正的通用指针,也缺乏打印函数指针的干净方法。
\n