C 为什么不同的格式说明符在printf中给出不同的输出?
我想知道为什么这段代码的输出是0?C 为什么不同的格式说明符在printf中给出不同的输出?,c,C,我想知道为什么这段代码的输出是0? y.beta和p->beta是同一个变量,所以输出不应该是3吗 int main() { struct MyType { int alpha; double beta; }; static struct MyType y; struct MyType *p = &y; y.alpha = 1; p->alpha = 2; p->beta = 2.5;
y.beta
和p->beta
是同一个变量,所以输出不应该是3吗
int main() {
struct MyType {
int alpha;
double beta;
};
static struct MyType y;
struct MyType *p = &y;
y.alpha = 1;
p->alpha = 2;
p->beta = 2.5;
y.beta = 1.5;
printf("%d", y.beta + p->beta);
return 0;
}
通过将错误类型的参数传递给
printf
,调用未定义的行为:
printf("%d", y.beta + p->beta);
%d
期望传递一个int
,y.beta+p->beta
是一个双值
将代码更改为:
printf("%f\n", y.beta + p->beta);
未定义的行为意味着任何事情都可能发生;试图理解它为什么打印0
,是徒劳的。其他事情可能会发生在不同的机器上,或者在不同的时间,或者即使下雨或者老板来了;-) 正如正确指出的,printf(“%d”,somevariable)
期望变量作为int
传递,而您的结果是double
类型值
%d
称为格式说明符。这是必需的,因为处理器以不同的方式传递和解释不同的数据类型,可能在内存中的不同位置或不同的寄存器中(如x86_64平台)。因此,即使是具有相同位模式的相同内存位置,也可能根据数据类型进行非常不同的解释。这就是另一个例子中发生的情况:
int main() {
int a = 1048577;;
printf("%d\n", a);
printf("%hd", a); //hd is the format specifier for short int
return 0;
}
输出:
1048577
1
如您所见,相同的变量a根据您指定的数据类型进行不同的解释
为什么会这样?
这是1048577的二进制表示(假设为32位int
):
如果格式说明符为short int
(%hd
),则is shorts为16位宽,仅使用值中的16个低位,因此输出为1
在某些体系结构(x86 32位)上可能会发生类似的情况,在其他体系结构上可能会发生更糟的情况,double
值以不同的方式传递,并且printf
从调用方未写入任何特定值且可能存在任何随机值的位置获取int
,例如0
解决方法是将代码修改为
printf(“%f”,y.beta+p->beta)
正如所指出的,%d
需要是%f
谢谢,为什么%d不工作@user3386109@Nona:%d表示数字(整数),%f表示浮点数。%d
用于打印整数,例如alpha
%f
用于打印浮点
或双精度
,例如beta
。即使您试图打印的数字恰好是一个整数,如果您在编译器中启用了警告(例如,gcc-Wall-g
),则表达式y.beta+p->beta
的类型为double
然后,您将在printf
上收到一条警告,并且本可以在不询问的情况下纠正您的错误。谢谢您的额外解释,但您的示例有点误导:%hu
需要无符号int
,但将其解释为un无符号short
。这不会调用未定义的行为,而在sizeof(long-long)!=sizeof(int)
。将其更正为%hd。现在看起来不错,还不完全好%hd
和%hu
都通过将int
或无符号int
参数分别强制转换为short
和无符号short
来重新解释参数。在您的解释中,您提到了最后8位,但实际上是最后16位,或者更多,这取决于short
的实际大小。此外,不同的类型可能会在不同的位置传递到printf
,因此关于如何解释位模式的讨论可能并不相关。我纠正了你的回答。
00000000 00010000 00000000 00000001