有什么方法可以在C99中获得fdopen功能吗?

shstlldc  于 2023-03-22  发布在  其他
关注(0)|答案(3)|浏览(106)

显然fdopen需要使用POSIX/gnu 99编译标准。我希望留在C99上。
我遇到这个问题是因为我使用open()来创建一个文件描述符,然后(因为我使用fgets())我需要一个通过fdopen()生成的FILE指针。不幸的是,fdopen()在C99中不可用。
有没有一种方法可以从符合C99的描述符中获得FILE结构?

gojuced7

gojuced71#

有没有一种方法可以从符合C99的描述符中获得FILE结构?
如果你说的“兼容C99”是指只依赖于C99指定的C标准库的特性,那么就不需要了。不过这也没关系,因为如果你只依赖于C99的标准库,首先就没有办法获取或使用文件描述符。通过C FILE对象管理的流是C99定义的文件的唯一表示。
另一方面,如果你想把自己限制在C99的语法和语义上,而不一定是它指定的标准库函数,那么是的:使用fdopen()。它完全符合您所描述的目的。
由于您似乎正在使用gcc,可能出现问题的原因是您希望使用-std=c99选项来编译以禁用语言扩展,并且您发现这也禁用了(或者至少不支持)某些函数的声明,这是因为-std选项会影响某些标准feature test macros的默认值。documentation for fdopen()说它需要各种特性测试宏中的一个:值大于0的_POSIX_C_SOURCE,或者_XOPEN_SOURCE,或者_POSIX_SOURCE。使用-std=gnu99,您可以获得所有用于此目的的设置,但使用-std=c99,您无法获得任何用于此工作的定义。
如果您想要最新版本POSIX的所有库特性(由glibc提供),则应确保_POSIX_C_SOURCE的定义值为200809L。(从POSIX.1-2017开始)。由于这种依赖性是源代码的特征,而不是编译条件的特征,你应该在你的源文件的最开始放一个合适的宏定义(也就是说,不要依赖于编译选项)。例如:

#ifdef _POSIX_C_SOURCE
#undef _POSIX_C_SOURCE
#endif
#define _POSIX_C_SOURCE 200809L

#include <stdio.h>
#include <fcntl.h>

// ...

宏应该在任何头为#include d之前定义。
然后,您应该能够使用gcc -std=c99进行编译,并且还具有fdopen()声明。

oprakyz7

oprakyz72#

fdopen()函数是POSIX的一部分,而不是C99的一部分。如果你在严格的C99模式下编译代码,就像-std=c99一样,你不会得到它。
当然,这是意料之中的--int文件描述符也不是C99的一部分。
获取函数的方法是在包含头文件之前定义正确的“功能测试宏”。在文件的顶部执行:

#define _POSIX_C_SOURCE 1

#include <stdio.h>

// use fdopen() here

您可以在手册页中找到有关这些要求的信息:
https://linux.die.net/man/3/fdopen
glibc的功能测试宏要求(参见feature_test_macros(7)):
fdopen(): _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _POSIX_SOURCE
“C99-compliance”是一个有趣的术语。如果你在POSIX或类似POSIX的系统(Linux,WSL)上,那么你有int文件描述符和fdopen(),一切都会正常工作。如果你试图编写在任何符合C99实现上运行的代码,那么你显然不能使用fdopen()-而且open()也不是C99的一部分。
对于open()不需要这样做的原因是因为open()是通过<fcntl.h>公开的,而<fcntl.h>不是C99的一部分。

2wnc66cl

2wnc66cl3#

不幸的是,fdopen()在C99中不可用。
open()也不是。这个问题是自相矛盾的。系统调用open()在任何版本的C标准中都没有指定(fopen()是),C也没有文件描述符的概念,它只处理流。
在手册页中:

CONFORMING TO         
       open(), creat() SVr4, 4.3BSD, POSIX.1-2001, POSIX.1-2008.

因此,如果您的应用程序已经在使用open(),那么没有理由避免使用fdopen()

/* See @John's answer for the rationale. */
#define _POSIX_C_SOURCE 200809L

#include <stdio.h>                                                                                    │
#include <stdlib.h>                                                                                   │
#include <unistd.h>                                                                                   │
#include <fcntl.h>                                                                                    │
                                                                                                      │
int main (int argc, char **argv)                                                                      │
{                                                                                                     │
        if (argv[1]) {                                                                                │
                int fd = open (argv[1], O_RDONLY);                                                    │
                FILE *stream = fdopen (fd, "r");                                                      │
        }                                                                                             │
                                                                                                      │
        return EXIT_SUCCESS;                                                                          │
}

编制单位:

gcc-10 -std=c99 open.c -o open

不再产生警告。

相关问题