c每次都有不同的输出?

时间:2017-01-29 12:44:16

标签: 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;
}

以上代码每次使用gcc生成不同的输出。为什么呢?

6 个答案:

答案 0 :(得分:2)

您为期望int%f的{​​{1}}格式传递float值('a')。这是未定义的行为,可能导致同一程序的每次执行都有不同的输出。第二个double存在同样的问题:printf需要%ffloat,但您传递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会升级为doubleprintf()类型的精度高于double类型,如果请求的小数位数多于提供的原始类型,则可能会输出误导性值。

建议始终使用float进行浮点计算,并为更适合的特定情况保留double类型,例如计算机图形API,某些二进制交换格式......

答案 1 :(得分:1)

%f说明符需要与浮点参数(floatdouble)匹配,而不是给它int。不匹配的类型是未定义的行为,这意味着它可以做任何事情,包括每次打印不同的结果。

希望这有所帮助,祝你好运:)

编辑:感谢chqrlie的澄清!

答案 2 :(得分:1)

不可预测的行为。

当您尝试使用不匹配格式说明符打印值时,编译器会提供不可预测的输出。使用%f作为charint的格式说明符的行为未定义。< / 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