为什么%d在代码中为*b和*c显示两个不同的值[b和c指向同一地址]

为什么%d在代码中为*b和*c显示两个不同的值[b和c指向同一地址],c,pointers,C,Pointers,考虑下面的代码 { float a=7.999,*b,*c; b=&a;c=b; printf("%d-b\n%d-c\n%d-a\n",*b,*c,a); } 输出: -536870912-b 1075838713-c -536870912-a 我知道我们不允许使用%d而不是%f,但为什么*b和*c给出两个不同的值? 两个人的地址都一样,有人能解释一下吗? 我想知道它背后的逻辑使用错误的转换规范调用未定义的行为。您可能会得到预期值或意外值。您的程序可能会崩溃,可能会在不同的编译器上

考虑下面的代码

{
float a=7.999,*b,*c;
b=&a;c=b;
printf("%d-b\n%d-c\n%d-a\n",*b,*c,a);
}
输出:

-536870912-b
1075838713-c
-536870912-a
我知道我们不允许使用%d而不是%f,但为什么*b和*c给出两个不同的值? 两个人的地址都一样,有人能解释一下吗?
我想知道它背后的逻辑

使用错误的转换规范调用未定义的行为。您可能会得到预期值或意外值。您的程序可能会崩溃,可能会在不同的编译器上给出不同的结果,或者出现任何意外行为

C11:7.21.6格式化输入/输出功能: 如果转换规范无效,则行为未定义。282)如果任何参数无效 对应转换规范的类型不正确,行为为 未定义

使用指定为“%d”的整数格式而不是正确使用指定为“%f”的浮点,这是alk以省略方式无法解释为“未定义行为”的


您需要使用正确的格式说明符。

以下是一个简单的示例:

#include <stdio.h>
int main() {
  float a=7.999, b=7.999;
  printf("%d-a\n%d-b\n",a,b);
}

我应该补充一点,就标准而言,这只是“未定义的行为”,因此上述解释(在gcc上测试)仅适用于某些实现。

可能有很多原因

最明显的是,您的平台在整数寄存器中传递一些整数,在浮点寄存器中传递一些浮点数,从而导致
printf
查找从未设置为任何特定值的寄存器

另一种可能性——变量大小不同。因此,
printf
正在查找未设置的数据或作为其他操作的一部分设置的数据

由于
printf
通过
..
获取其参数,因此类型协议对于确保函数的实现甚至在正确的位置查找其参数是至关重要的


您必须对您的平台有深入的了解和/或深入挖掘生成的汇编代码才能确定。

您正在观察未定义行为的奥秘。OP似乎完全意识到进入了不安全的领域@在你的机器上,sizeof(float)==sizeof(int)吗?如果没有,则第二个%d可能正在打印*b而不是*c的一部分。正如其他人所提到的-这是未定义的行为。但是传递到省略号的
float
表达式被提升为
double
(并且
%f
处理一个
double
,而不是
float
)。如果您真的想知道会发生什么,查看生成的汇编代码。这根本没有回答问题。答案可能被否决了,因为它也没有给出OP实际观察者的任何具体原因,就像其他答案/注释一样。@alk;如果行为未定义,则所有赌注均已取消@alk;如果是这样的话,那么C标准必须删除这个引用或者应该修改它。我指的是“所有赌注都被取消”,因为一个或另一个实现可能有“扩展”,或者至少有可预测的行为。或者a1、a2、b1、b2而不是a、b、a、b呢?我使用了:
printf(%d-%d-b\n%d-%d-C\n%d-%d-a\n、*b、*C、a)和输出为:-536870912-1075838713-b-536870912-1075838713-c-536870912-1075838713-a
#include <stdio.h>
int main() {
  float a=7.999, b=7.999;
  printf("%d-a\n%d-b\n",a,b);
}
  printf("%d-a1\n%d-a2\n%d-b1\n%d-b2\n",a,b);