我有快速编译g ++版本3.something的代码.然后我想构建一些其他包含C++ 11符号的代码,所以我升级到g ++ 4.7.现在我的原始代码没有构建.我收到错误:
'fdopen'未在此范围内声明
根据手册页,fdopen()在stdio.h中声明,我包括在内.我不确定它是否相关,但我在Cygwin环境中工作.我使用的g ++的确切版本是Cygwin提供的版本4.7.2.
我没有更改此代码,因为我切换了编译器,我可以肯定地确认它已构建,我的测试代码运行并通过以前的编译器传递.
根据要求,演示问题的示例代码:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, char **argv)
{
int fd;
FILE *fp;
fd = open("test.txt", (O_WRONLY | O_CREAT | O_EXCL), S_IRWXU);
if(0 < fd)
{
fp = fdopen(fd, "wb");
fprintf(fp, "Testing...\n");
fclose(fp);
}
return 0;
}
# g++ -std=c++11 -o test test.cpp
test.cpp: In function 'int main(int, char**)':
test.cpp:14:29: error: 'fdopen' was not declared in this scope
Run Code Online (Sandbox Code Playgroud)
无论你做什么,请不要乱用__STRICT_ANSI__旗帜.该符号由GCC控制.你应该让海湾合作委员会对其进行定义而不管它.
你真正想要的是_POSIX_C_SOURCE功能测试宏.你看,fdopenC语言标准没有定义.当你告诉GCC你正在编写一个C++ 11程序时,GCC进入"严格"模式,它试图不定义任何未被语言定义的函数.这是为了避免与您自己的代码发生名称冲突.例如,一个有效的C++ 11程序可以自由定义它自己的函数,fdopen因为fdopen它不是该语言中的保留标识符.
但fdopen 是由POSIX定义,这是一个标准的,其包括,但是从,C语言标准分开.在编写使用POSIX函数的应用程序时fdopen,您必须告诉系统您打算编写POSIX应用程序,以便它知道它应该使POSIX定义的函数可用于您的程序.这是_POSIX_C_SOURCE功能测试宏的用武之地.在每个源文件的顶部,在包含任何标头之前,将此宏定义为适当的值.例如:
#define _POSIX_C_SOURCE 200112L
Run Code Online (Sandbox Code Playgroud)
您应该在定义中使用的值取决于您要定位的POSIX版本.如果您不确定要定位的版本,则可以定位与主机系统兼容的版本.您可以通过getconf从shell 运行来确定:
$ getconf _POSIX_VERSION
200809L
$ _
Run Code Online (Sandbox Code Playgroud)
在这里,我的系统告诉我它符合POSIX版本200809L(即POSIX.1-2008).我可以#define _POSIX_C_SOURCE 200809L在我的源代码中,并确信我的系统支持的所有标准功能都将提供给我.
问题来自-std=c++11. 该fdopen()函数不在 ANSI C 中(仅在 POSIX 标准中),并且使用-std=c++11选项编译意味着定义__STRICT_ANSI__,这会从 中排除几个函数stdio.h。顺便说一句,在 C++ 程序中,您通常应该包含<cstdio>而不是<stdio.h>,请参阅此处:stdio.h not standard in C++?。
如果您需要使用fdopen(),您可能需要-std=c++11在编译时删除该选项。另一种可能的解决方案虽然不是很优雅,但可以在源代码中使用它:
#ifdef __STRICT_ANSI__
#undef __STRICT_ANSI__
#include <cstdio>
#define __STRICT_ANSI__
#else
#include <cstdio>
#endif
Run Code Online (Sandbox Code Playgroud)
(旨在使用和不使用该-std=c++11选项)。