Gov*_*mar 26 c c++ floating-point printf cout
我正在使用Visual C++ 2012并从命令行编译以下文件:
#include <stdio.h>
int main()
{
printf("%.5f", 18/4+18%4);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
链接MSVCRT.LIB而不是LIBCMT以避免运行时错误R6002.
对于此程序,输出的值为0.00000.
但是,如果我在C++中执行完全相同的操作
#include <iostream>
using namespace std;
int main()
{
cout << 18/4+18%4 << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
现在,它打印出6,就像它应该的那样.
有什么不同?它与语言本身(C vs C++)或输出方法(cout vs printf)有关,还是只是与MSVC的怪癖?
Esc*_*alo 64
表达式18/4+18%4求值为a int,并且您正在请求浮点数.你应该总是在启用警告的情况下进行编译,并注意它们(他们说警告是等待发生的错误,并且它们是正确的).
这就是我的编译器(GCC 4.8.1)告诉我的(甚至没有强制执行-Wall):
warning: format ‘%.5f’ expects type ‘double’, but argument 2 has type ‘int’
Run Code Online (Sandbox Code Playgroud)
另一方面,该std::cout<<操作能够推断出表达式的类型并将其正确地流式传输到屏幕上.
Gab*_*abe 37
C函数正在传递一个整数,但是你告诉它(with %f)期望一个双精度浮点数,所以它失败了.C++函数知道它正在传递一个整数,因此它可以正常工作.
Sha*_*our 12
在Ç示例此表达式18/4+18%4将评估为一个INT由于所有操作数都是整数常量但要指定这是一个双向printf,因此它是将被错误地处理.另一方面,如果您在表达式的除法部分中使用了浮点常量,例如18.0/4+18%4整个表达式将计算为double.或者,您也可以使用"%d"格式说明符.
这也是错误地指定格式的未定义行为printf,这也说明了为什么构建警告很重要,使用gcc -Wall我收到以下警告(请参见实时):
warning: format ‘%f’ expects argument of type ‘double’, but argument 2 has type ‘int’
Run Code Online (Sandbox Code Playgroud)
在C++中, std :: cout的operator <<有一个重载int,因此在这种情况下会被调用.我们可以看到这个重载是C++草案标准所要求的许多其他重载,在27.7.3.1 类模板basic_ostream中我们找到以下运算符声明:
basic_ostream<charT,traits>& operator<<(int n);
Run Code Online (Sandbox Code Playgroud)
为了完整起见,盘旋回未定义的行为,在C99标准草案中部分7.19.6.1 fprintf函数其中printf的部分是指回到格式字符串的第9说:
如果转换规范无效,则行为未定义.[...]
vil*_*lla 11
表达方式
18 / 4 + 18 % 4
Run Code Online (Sandbox Code Playgroud)
评估为int.
但printf格式字符串"%.5f"需要加倍.
使用c ++和ostreams,语言可以自动确定输出类型.
只需将您的C代码更改为以下内容:
#include <stdio.h>
int main()
{
printf("%d", 18 / 4 + 18 % 4);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
其他人已正确指出printf()语句中的int/double不匹配.我只想评论你的声明,"链接MSVCRT.LIB而不是LIBCMT,以避免运行时错误R6002." 这个简单的程序不应该对运行时环境造成过度负担,因此像这样的运行时错误应该是代码中未定义行为的红色标志.
一个快速的谷歌"MSVCRT R6002"说:
C运行时错误R6002 浮点支持未加载
必要的浮点库没有链接.通过检查以下可能的原因来解决问题
- 该程序是编译或链接的选项,如/ FPi87,需要一个协处理器,但该程序是在没有安装协处理器的机器上运行的.
- printf_s或scanf_s函数的格式字符串包含浮点格式规范,程序不包含任何浮点值或变量.
- 编译器通过仅在必要时加载浮点支持来最小化程序的大小.编译器无法检测格式字符串中的浮点格式规范,因此它不会加载必要的浮点例程.
- 使用浮点参数对应浮点格式规范,或在程序中的其他位置执行浮点赋值.这会导致加载浮点支持.
- 在混合语言程序中,在链接程序时,在FORTRAN库之前指定了C库.最后重新链接并指定C库.
当然,这里的教训是你应该密切关注编译器和运行时警告和错误.如有疑问,请始终假设问题出在您的代码中,而不是编译器中.
| 归档时间: |
|
| 查看次数: |
3232 次 |
| 最近记录: |