每次在c中输出不同?
我正在努力学习C语言,我已经很困惑了每次在c中输出不同?,c,printf,format-specifiers,C,Printf,Format Specifiers,我正在努力学习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; } #包括 内部主(空) { INTA=50000; 浮动b='a'; printf(“b=%f\n”,“a”); printf(“a=%f\n”,a); 返
#include <stdio.h>
int main(void)
{
int a = 50000;
float b = 'a';
printf("b = %f\n", 'a');
printf("a = %f\n", a);
return 0;
}
#包括
内部主(空)
{
INTA=50000;
浮动b='a';
printf(“b=%f\n”,“a”);
printf(“a=%f\n”,a);
返回0;
}
上述代码每次使用
gcc
生成不同的输出。为什么?指定符%f
需要与浮点参数(float
或double
)匹配,而不是给它int
s。不匹配类型是未定义的行为,这意味着它可以做任何事情,包括每次打印不同的结果
希望这有帮助,祝你好运:)
编辑:感谢chqrlie的澄清 不可预测的行为 当您尝试使用不匹配的格式说明符打印值时,编译器会给出不可预测的输出。使用
%f
作为字符
和整数
的格式说明符的行为未定义
根据数据类型在程序中使用正确的格式说明符:
printf("%d\n", 'a'); // print ASCII value
printf("%d\n", a);
您为
%f
格式传递一个int
值('a'),该格式应为float
或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;
}
在启用更多警告的情况下编译,使用命令行参数-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
在传递到printf()时升级为double
。double
类型比float
类型具有更高的精度,如果请求的小数比原始类型多,则可能会输出误导性的值
建议始终使用double
进行浮点计算,并将float
类型保留为更适合的特定情况,例如计算机图形API、某些二进制交换格式…首先,gcc应针对上述代码发出警告。这是因为格式说明符不匹配
不匹配的格式(printf()
以及scanf()
)将在C中产生不可预测的行为。尽管gcc希望隐式地处理可能的类型转换,如int
到float
这里有两个很好的参考资料。
以下内容将按预期工作
#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;
}
#包括
内部主(空)
{
INTA=50000;
浮动b='a';
printf(“b=%f\n”,(float)“a”);
printf(“a=%f\n”,(float)a);
返回0;
}
从实现的角度来看,将浮点数(即%f
所期望的)作为变量参数列表(即..
在printf
原型中的含义)和整数(即'a'
是什么,特别是int
类型)传递可能会使用不同的寄存器和内存布局
这通常由ABI调用约定定义。具体来说,在x86_64中,%xmm0
将由printf读取(使用单位化值),但gcc将在printf
调用中填充%rdi
详见第页。56
您应该注意到,C是一种非常低级的语言,它在实现过程中会遇到很多令人困惑的情况(包括整数溢出和下溢、单位化变量、缓冲区溢出)。这允许获得最大的性能(通过避免大量的检查),但会留下诸如此错误之类的错误 您面临的主要困难是所使用的数据类型。
当您创建一个变量时,您告诉内存必须保留的大小才能正常工作。像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);
有关详细信息:在第一条printf
语句中,您尝试将char
打印为float
。这可能是部分原因。使用不匹配的格式和参数类型是未定义的行为。请认真对待编译器的警告。您应该了解格式说明符。是否要执行浮点b='a'?而且不仅仅是=一个?%f
实际上需要一个浮点
或双
参数<当传递到printf
(和任何其他可变函数)时,code>float
参数将升级为double
'a'
在C中不是char
,而是int
值。顺便说一句,char
值在传递到printf
时会隐式提升为int
。
char a = 'a';
printf("%c",a);
int b = 50000;
printf("%d",b);
float c = 5.7;
printf("%f", c);