【问题标题】:Printing addition of char and integer value as float将字符和整数值的加法打印为浮点数
【发布时间】:2021-09-15 19:14:13
【问题描述】:

我只是想知道为什么当我尝试打印 char 和整数值的加法时会得到 0 值。我的代码如下:

int y;
y = 10;

char z;
z = '9';
printf("%f", z + y);

【问题讨论】:

  • 因为z + y 产生int,而不是float?因此,您的 printf 调用会调用 undefined behavior
  • 由您来确保格式字符串和参数匹配。在您的示例中,格式字符串调用double,但参数是int。因此,您要么需要更改格式字符串,要么向参数添加强制转换。
  • 如果您的编译器警告级别设置得足够高,您可能会收到有关格式与参数不匹配的警告。这将是一件值得关注的好事情。

标签: c printing


【解决方案1】:

这个 printf 调用

printf("%f", z + y);

调用未定义的行为,因为您将错误的转换说明符 %f 与 int 类型的对象一起使用。

你需要像例子一样转换参数

printf( "%f", ( double )( z + y ) );

printf( "%f", ( float )( z + y ) );

尽管在最后一种情况下,由于默认参数提升,参数将被提升为 double 类型。

【讨论】:

【解决方案2】:

大多数时候,当你调用一个函数并且你传递了错误类型的参数时,C 会自动为你转换它。例如,如果我写

#include <math.h>

int i = sqrt(144);
printf("%d\n", i);

这有效,并打印12。即使sqrt 函数实际上需要double 类型的参数,它仍然有效——因为编译器知道这一点,并在将其传递给sqrt 之前自动将我的int 参数144 转换为double。 (回来的路上还有一个转换,因为sqrt返回一个double,必须先转换回int再赋值给i。)

但是printf 函数本身是这条规则的一个巨大的例外。在您的代码中,您有

printf("%f", z + y);

现在,你和我都知道%f 想要double,但这不是传统上C 语言可以知道的东西。就 C 语言而言,printf 函数采用一个 const char * 类型的参数(即一个字符串),然后可能还有一些其他参数,具体取决于特定的 % 序列在运行时在格式字符串中找到。所以编译器只是半心半意地尝试,将它们转换为一些常见的类型,然后将它们传递给printf 以完成其余的工作。在您的示例中,由于zcharyintz + y 将是int,这就是传递给printf 的内容。当printf 咀嚼格式字符串并找到格式说明符%f 时,它无法知道实际传递的参数类型,因此它甚至无法尝试自己进行任何转换。它所能做的就是假设你实际上传递了一个double——而且,因为你没有传递,所以你得到了一个无意义的值。

现在,尽管正如我刚刚解释的那样,编译器传统上没有任何许可来尝试将 printf 参数转换为正确的类型,但现代编译器通常查看一下格式字符串,如果可以的话,并检查事情在运行时是否能正常工作。例如,当我通过我的一个编译器运行您的代码时,我得到warning: format specifies type 'double' but the argument has type 'int'。如果你的编译器没有给你这样的警告,你可能想知道是否有办法启用它们,因为它们显然非常方便。

【讨论】:

【解决方案3】:

正如 cmets 部分已经指出的,您有责任确保格式字符串和函数参数匹配。在您的情况下,它们不匹配。表达式z + y 的结果是int 类型,但您在格式字符串中使用了%f 转换说明符,它仅对数据类型floatdouble 有效(float@ 987654321@ 到 double)。

正如 cmets 部分所指出的,您有两个选项可以解决此问题:

  1. 更改格式字符串以期望int 类型的参数,或者
  2. 将参数转换为doublefloat

使用选项 #1 的解决方案如下所示:

换行

printf("%f", z + y);

printf("%d", z + y);

使用选项 #2 的解决方案如下所示:

换行

printf("%f", z + y);

printf("%f", (double) (z + y) );

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-05-29
    • 2019-01-10
    • 2012-06-12
    • 1970-01-01
    • 2021-07-29
    • 2012-06-10
    • 1970-01-01
    相关资源
    最近更新 更多