考虑代码
#include <iostream>
int main() {
std::cout << 4.2L;
}
在MinGW上进行编译并在以下输出中运行结果:
> g++ test.cc
> a.exe
-7.89773e-278
它是否是MinGW中的错误,是否有修复或解决方法?
更新
this question中描述的printf
存在类似问题:
#include <cstdio>
int main() {
std::printf("%Lg", 4.2L); // prints -7.89773e-278
}
但是,printf
的问题可以通过定义__USE_MINGW_ANSI_STDIO
来解决,而这个问题可以解决,所以我认为它应该是一个单独的问题。
答案 0 :(得分:1)
这是不一个MinGW错误......这个陈述似乎有争议,实际情况是它是微软C / C ++运行时库的限制,MinGW就是依赖。作为开发人员,您有责任了解工具的局限性,例如本工具的限制,并在这些限制范围内工作。
您遇到的问题是由于Microsoft在MSVC中缺少long double
数据类型的任何明显实现,因此I / O子系统中缺少对该数据类型的有效支持由MSVCRT.DLL提供; (并且,在您告诉我之前,也许是愤怒的,当然,MSVC支持long double
&#34;,我知道它语法,但语义< / em>它没有明确的实现,只是通过有效地忽略long
限定符来表现,使long double
成为裸double
的同义词。
相反,GCC和MinGW 确实的实现为long double
,与double
不同;前者是80位实体,而后者是64位,并且是MSVC的两种数据类型的64位实现的精确模拟。当您需要80位浮点计算的更高精度时,这很好,但是当涉及到输出结果时,它可能会导致问题,例如您遇到的问题; (I / O转换器是一个long double
数据实体的80位原始数据表示,它需要64位;内部表示不相同,所以当尾数的一部分被解释为指数)。
正如您已经注意到的那样,虽然MSVCRT.DLL仅支持64位double
值的输出,但MinGW确实提供了C&#39 printf
样式I / O的替代实现,可以正确翻译80位格式;但是,这并没有扩展到支持C ++样式的I / O.因此,在C ++代码中,您不能简单地利用MinGW替代I / O实现,同时继续使用C ++ I / O语义;您必须识别MSVCRT.DLL限制,并相应地编写应用程序代码。您可以考虑的一些选项包括: -
long double
数据类型,并按double
执行计算; (这是 only 选项,有效选项可供Microsoft编译器的用户使用,因为它并不真正具有独特的long double
数据类型实现开始)。long double
执行计算,但将结果转换为double
以进行输出。printf
,-posix
中的任何一个进行编译来启用MinGW的替代-D_GNU_SOURCE
实现, -D_BSD_SOURCE
,-D_XOPEN_SOURCE=700
或-D_POSIX_C_SOURCE=200809L
,或者更好的是,将#define
添加到您的来源中的任何一个,之前 {{ 1}})。如果愿意,您也可以替换#include
或_XOPEN_SOURCE
的任何早期合规级别; (但是,请忽略一些评论员提供的令人难以置信的错误建议,以_POSIX_C_SOURCE
进行编译;引入该宏名称的双下划线将其标记为&#34 ;实现保留&#34;,因此,作为编译器实现的最终用户,您不应该直接引用它。-D__USE_MINGW_ANSI_STDIO
函数将snprintf
数据转换为C字符串表示,然后使用C ++语义输出,而不是让C ++转换{{1的原始形式实体直接。 (IIRC,Microsoft不提供long double
- 他们提供long double
- 所以如果您小心使用ANSI函数名称,您将获得80位snprintf
支持自动地)。