【问题标题】:Address of variables in C using %p使用 %p 的 C 中变量的地址
【发布时间】:2018-04-15 10:13:27
【问题描述】:

例如,

int a = 6;
printf("%p", &a);

这会打印出右指针的地址吗? 但是如果我们在没有 & 的情况下打印呢?

int a = 6;
printf("%p", a);

谁能告诉我打印出来的是什么?

【问题讨论】:

  • 你试过了吗?
  • %p Format specifier in c的可能重复
  • 你的编译器没有给出任何警告吗?!
  • 是的,没有警告...

标签: c pointers


【解决方案1】:

这是未定义的行为,因为 %p 需要 void*

printf("%p", a);

允许添加显式转换,但行为是实现定义的:

printf("%p", (void*)a);

“实现定义”意味着编译器在将int 转换为void* 时可以随意做任何事情。请参阅 this Q&A 以获取标准中的确切引用。

在许多实现中,您会看到一个分配了数字值int (demo 1) 的指针。其他实现会警告您该行为毫无意义。如果您将警告视为错误,则代码将无法编译 (demo 2)。

【讨论】:

  • "在将 int 转换为 void* 时,编译器可以随意执行任何操作。"嗯,没有。编译器必须按照实现的定义去做。例如,它不依赖于优化(在任何健全的实现上)。
  • @hyde loop { putchar('?'); },如果编译器不是“实现”,你认为它是什么?你是说操作系统吗?这是非常不同的概念! Clang 可以为所欲为,而 GCC 可以为所欲为。 “在将 int 转换为 void* 时,编译器可以随意做任何事情。”完全正确的定义是实现的行为。
  • @Stargateur 我的意思是,如果它是未定义的行为,编译器可以为所欲为。如果它是实现定义的行为,编译器必须完全按照它的定义去做,你可以找到并依赖它,并利用例如配置脚本和使用 #ifdefs 等(只要实现不改变,它通常不经常这样做,因为不幸的是有很多代码取决于实现定义的行为)。
【解决方案2】:

根据 C 标准,将错误的匹配类型参数发送到 printf() 是未定义的行为。还有int != void *,所以这是未定义的行为。

除非在随后的详细描述中另有明确说明,否则以下每个语句均适用:如果函数的参数具有无效值(例如函数域之外的值,或地址空间之外的指针程序,或空指针,或指向不可修改存储的指针(当相应的参数不是 const 限定时)或具有可变数量参数的函数不期望的类型(提升后),行为未定义。

Source


顺便说一句,这就是为什么你应该写printf("%p", (void *)&a);

warning: format specifies type 'void *' but the argument has type 'int *' [-Wformat-pedantic]
printf("%p", &a);
        ~~   ^~

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多