【发布时间】:2014-09-12 02:50:59
【问题描述】:
在最近的一个问题中,有人提到用 printf 打印指针值时,调用者必须将指针强制转换为 void *,如下所示:
int *my_ptr = ....
printf("My pointer is: %p", (void *)my_ptr);
对于我的一生,我无法弄清楚为什么。我找到了this question,几乎是一样的。问题的答案是正确的 - 它解释了整数和指针的长度不一定相同。
当然,这是真的,但是当我已经有一个指针时,就像上面的例子一样,我为什么要从int * 转换为void *?什么时候 int * 与 void * 不同?事实上,(void *)my_ptr 何时生成任何不同于简单的my_ptr 的机器代码?
更新:
多位知识渊博的响应者引用了该标准,称传递错误的类型可能会导致未定义的行为。如何?我希望printf("%p", (int *)ptr) 和printf("%p", (void *)ptr) 生成完全相同的堆栈帧。这两个调用何时会生成不同的堆栈帧?
【问题讨论】:
-
您将获得一大堆“未定义行为”的答案,本质上,您使用
int*或void*没有区别(正如您所说,没有机器为这种类型的转换生成代码)。 -
实际上,我得到了一些很好的答案来解释理论上的差异。
-
如果您找到一个平台(编译器、链接器、IDE、CPU、操作系统等),在该平台下这两个选项会产生两个不同结果,请告诉我...事实上,如果您可以将此要求作为问题的一部分添加,那将会很有趣...
-
关于不同类型的指针表示可能不同的“真实架构”,请参阅此最佳答案:stackoverflow.com/questions/8007825/…。 char/void 指针与字指针具有不同的表示形式。
-
@barakmanos “使用
int*或void*没有区别”是一个危险的低标准编码。它的真正意思是“在我尝试的极少数情况下,我没有注意到失败。”当您编写导致未定义行为的代码时,您永远不知道将来何时会失败。升级你的 C 库? BOOM! 使用新版本的编译器重新编译? BOOM 将您的代码移植到另一个架构? BOOM 在完美的条件下编写没有错误的 C 代码已经够难的了。在您的代码中故意 UB 没有可接受的理由。永远。
标签: c pointers casting printf void