我正在努力学习C并且我已经非常困惑。
#include <stdio.h>
int main(void)
{
int a = 50000;
float b = 'a';
printf("b = %f\n", 'a');
printf("a = %f\n", a);
return 0;
}
以上代码每次使用gcc
生成不同的输出。为什么呢?
答案 0 :(得分:2)
您为期望int
或%f
的{{1}}格式传递float
值('a')。这是未定义的行为,可能导致同一程序的每次执行都有不同的输出。第二个double
存在同样的问题:printf
需要%f
或float
,但您传递double
值。
以下是更正后的版本:
int
输出:
#include <stdio.h>
int main(void) {
int a = 50000;
float b = 'a';
printf("a = %d\n", a);
printf("b = %f\n", b);
printf("'a' = %d\n", 'a');
return 0;
}
使用更多警告进行编译,使用命令行参数a = 50000
b = 97.000000
'a' = 97
可以让编译器执行更多的一致性检查并抱怨潜在的编程错误。它会在发布的代码中检测到错误。
确实-Wall -W -Wextra
仍抱怨上述纠正:
clang
传递给clang -O2 -std=c11 -Weverything fmt.c -o fmt
fmt.c:8:24: warning: implicit conversion increases floating-point precision: 'float' to 'double' [-Wdouble-promotion]
printf("b = %f\n", b);
~~~~~~ ^
1 warning generated.
后, b
会升级为double
。 printf()
类型的精度高于double
类型,如果请求的小数位数多于提供的原始类型,则可能会输出误导性值。
建议始终使用float
进行浮点计算,并为更适合的特定情况保留double
类型,例如计算机图形API,某些二进制交换格式......
答案 1 :(得分:1)
%f
说明符需要与浮点参数(float
或double
)匹配,而不是给它int
。不匹配的类型是未定义的行为,这意味着它可以做任何事情,包括每次打印不同的结果。
希望这有所帮助,祝你好运:)
编辑:感谢chqrlie的澄清!
答案 2 :(得分:1)
不可预测的行为。
当您尝试使用不匹配格式说明符打印值时,编译器会提供不可预测的输出。使用%f
作为char
和int
的格式说明符的行为未定义。< / p>
根据您的数据类型在程序中使用正确的格式说明符:
printf("%d\n", 'a'); // print ASCII value
printf("%d\n", a);
答案 3 :(得分:1)
从实现的角度来看,将浮点数(即%f
所期望的)作为变量参数列表传递(这是...
在printf
原型中的含义)和整数(即'a'
,特别是类型int
)可以使用不同的寄存器和内存布局。
这通常由 ABI调用约定定义。具体来说,在x86_64中,%xmm0
将由printf读取(具有单位化值),但gcc将在%rdi
调用中填充printf
。
请参阅System V Application Binary Interface AMD64 Architecture Processor Supplement中的详情。 56
你应该注意到C是一种非常低级的语言,它在实现的肩膀上放置了许多令人困惑的情况(包括整数溢出和下溢,单元化变量,缓冲区溢出)。这样可以获得最大的性能(通过避免大量检查),但会留下诸如此错误之类的错误。
答案 4 :(得分:0)
首先,gcc应该对上面的代码发出警告。这是因为格式说明符不匹配。
格式不匹配(printf()
以及scanf()
)会在C中产生不可预测的行为。尽管gcc预计会照顾int
等可能的类型转换隐含地float
。
以下是两个不错的参考文献
https://stackoverflow.com/a/1057173/4954434
https://stackoverflow.com/a/12830110/4954434
以下将按照预期的方式工作。
#include <stdio.h>
int main(void)
{
int a = 50000;
float b = 'a';
printf("b = %f\n", (float)'a');
printf("a = %f\n", (float)a);
return 0;
}
答案 5 :(得分:0)
您遇到的主要困难是您正在使用的数据类型。
当您创建变量时,您将告诉内存必须保留以便正常工作的大小。类似char
的大小为1字节,int
等于4字节,float
为32字节。使用相同的数据类型不会产生不可预测的结果非常重要。
char a = 'a';
printf("%c",a);
int b = 50000;
printf("%d",b);
float c = 5.7;
printf("%f", c);
有关详细信息:C-Variables