为什么来自 printf 的相同表达式的输出与 cout 不同
Why does this output of the same expression from printf differ from cout?
我正在使用Visual C++ 2012并从命令行编译以下文件:
#include <stdio.h>
int main()
{
printf("%.5f", 18/4+18%4);
return 0;
}
与 MSVCRT 链接。LIB 而不是 LIBCMT 以避免运行时错误 R6002。
对于此程序,输出的值为 0.00000。
但是,如果我在C++中执行完全相同的事情
#include <iostream>
using namespace std;
int main()
{
cout << 18/4+18%4 << endl;
return 0;
}
现在,它打印出 6,就像它应该的那样。
有什么区别?是与语言本身(C vs C++(还是输出方法(cout vs printf(有关,还是只是MSVC的一个怪癖?
表达式18/4+18%4
的计算结果为 int
,并且您正在请求浮点数。您应该始终在启用警告的情况下进行编译,并注意它们(他们说警告是一个等待发生的错误,他们是对的(。
这是我的编译器(GCC 4.8.1(告诉我的(即使没有强制执行-Wall
(:
warning: format ‘%.5f’ expects type ‘double’, but argument 2 has type ‘int’
另一方面,std::cout<<
操作能够推断出表达式的类型并将其正确流式传输到屏幕。
C 函数正在传递一个整数,但您告诉它(使用 %f
(期望双精度浮点数,因此它失败。C++函数知道它正在传递一个整数,因此它可以正常工作。
在 C 示例中,此表达式18/4+18%4
计算结果为 int,因为所有操作数都是整数常量,但您指定它是 printf
的双精度,因此处理不正确。另一方面,如果您在表达式的除法部分使用了浮点常量18.0/4+18%4
则整个表达式的计算结果将变为双精度数。或者,您也可以在格式说明符中使用"%d"
。
这也是错误地指定要printf
格式的未定义行为,这也说明了为什么使用警告构建很重要,使用 gcc -Wall
我收到以下警告(实时查看(:
warning: format ‘%f’ expects argument of type ‘double’, but argument 2 has type ‘int’
在 C++ std::cout 的运算符中<<具有 int
的重载,因此在这种情况下将调用该运算符。我们可以看到C++草案标准需要的重载,在类模板27.7.3.1
部分中basic_ostream我们找到了以下运算符声明:
basic_ostream<charT,traits>& operator<<(int n);
为了完整起见,回到未定义的行为,C99 草案标准在第 7.19.6.1
节中 printf
部分引用的格式字符串第 9 段的 fprintf 函数说:
如果转换规范无效,则行为未定义。[...]
表达式
18 / 4 + 18 % 4
计算结果为 int。
但是 printf 格式字符串 "%.5f"> 需要双精度。
使用 c++ 和 ostreams,语言可以自动确定输出类型。
只需将您的 C 代码更改为以下内容:
#include <stdio.h>
int main()
{
printf("%d", 18 / 4 + 18 % 4);
return 0;
}
其他人正确地指出了 printf(( 语句中的 int/double 不匹配。 我只想评论你的声明,"与MSVCRT链接。LIB 而不是 LIBCMT 以避免运行时错误 R6002。 这么简单的程序不应该过度地增加运行时环境的负担,因此像这样的运行时错误应该是代码中未定义行为的危险信号。
快速谷歌"MSVCRT R6002"说:
C 运行时错误 R6002 未加载浮点支持
未链接必要的浮点库。 通过检查以下可能的原因进行修复
该程序是使用需要协处理器的选项(
- 如/FPi87(编译或链接的,但该程序在未安装协处理器的计算机上运行。
- printf_s或scanf_s函数的格式字符串包含浮点格式规范,程序不包含任何浮点值或变量。
- 编译器通过仅在必要时加载浮点支持来最小化程序的大小。编译器无法检测格式字符串中的浮点格式规范,因此它不会加载必要的浮点例程。
使用浮点参数对应于浮点- 格式规范,或在程序的其他位置执行浮点赋值。这会导致加载浮点支持。
在- 混合语言程序中,在链接程序时,在 FORTRAN 库之前指定了 C 库。最后重新链接并指定 C 库。
当然,这里的教训是,你应该密切关注编译器和运行时的警告和错误。 如有疑问,请始终假设问题出在您的代码中,而不是编译器中。
在 C 中,因为您在 printf 格式说明符中显式指定浮点 ("%f"(,所以它需要一个浮点参数。 但是你给了它一个"int"参数,因此问题来了。
根据您要执行的操作,您可以:
1( 将你的(否则是整数的(表达式转换为浮点
数和/或
2(在cout流中使用setprecision,就像在C中使用"%.5f"一样:
#include <iostream>
using namespace std;
int main()
{
float x = 18/4+18%4;
std::cout << std::setprecision(5) << x << endl;
return 0;
}
3(如果你想要整数,使用printf ("%d", 18/4+18%4);
如果你想要相同的行为(和响应(,你最好编码
printf("%dn", 18/4 + 18%4);
获取 int 响应而不是浮点响应。 您将获得与所选运算符相同的结果<<
ostream& std::operator<<(ostream&, const int);
否则,您可以显式使用
printf("%.5fn", (double)(18/4 + 18%4));
得到6.00000
结果。
让其中一个数字成为浮点值:
#include <stdio.h>
int main()
{
printf("%.0f", 18/4.0+18%4);
return 0;
}
<</div>
div class="answers"> 一种可能的替代方法是,类型转换文本(或表达式本身(:
#include <stdio.h>
int main(void)
{
printf("%.5f", (float)18/4+18%4);
return 0;
}
- 为什么在C的循环中使用printf的Rust代码不显示输出,而在C++的循环中显示std::cout
- std::cout输出int时出现编译错误
- COUT 无法提供输出可能是由于内联组装
- 为什么我的 cout 在输出中没有显示字符串?
- 调用 cout 时如何在结构中输出常量文本?
- 如何在C++中编写 ostream 的向量,它接收所有不同的输出流,如 cout、ostringstream 和 ofs
- Vscode/C++ - cout 无法输出完整的句子,也无法与整数连接
- 我的 cout 上有一个奇怪的输出,它把答案放在第一位,然后在我调用它的地方放一个奇怪的输出.我该怎么办?
- 在 CPP 中使用 cout 的重复输出
- 在 c++ 中使用 cout.precision() 的奇怪输出
- 为什么'std::cout << !+2 '输出 0?
- 对于输出,std::copy是否比std::cout快
- 在视觉工作室中以十六进制进行位移位并通过 cout 输出
- 输出使用 cout 转换为 ASCII 的文本时输出格式不正确,C++
- 如何从控制台 c++(从 cout)捕获输出
- 为什么cout输出内存地址不是字符串?
- Jupyter笔记本未显示C 输出(COUT)
- 输出 cout 是感叹号.C++
- 无法从C++循环实现所需的输出 (COUT)
- "定向到标准输出(cout)"是什么意思?