错误"'fdopen'未声明为"使用g ++ 4编译,使用g ++ 3编译

Ala*_*irG 5 c++ g++-4.7

我有快速编译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)

Dan*_*ing 8

无论你做什么,请不要乱用__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在我的源代码中,并确信我的系统支持的所有标准功能都将提供给我.

  • @Ale:更正:MinGW不使用Newlib.但是他们的头文件有同样的错误(可能是由于他们与Cygwin共享的祖先;或者它可能只是**程序员常常不理解POSIX功能测试宏).在任何情况下,MinGW都是一个糟糕的例子,因为MinGW开发人员声称他们没有开发符合POSIX的系统.在不符合POSIX标准且不希望符合POSIX标准的系统上测试POSIX功能(如`fdopen`)是没有意义的. (2认同)

Ale*_*Ale 4

问题来自-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选项)。