有没有办法在GCC中使用fopen_s()或者至少创建一个#define?

Sha*_*tia 14 c gcc fopen visual-c++

MSVC编译器说不fopen()推荐使用,并建议使用fopen_s().

有什么方法可以使用fopen_s()并且仍然可移植吗?

#define什么想法?

Ale*_*x B 28

Microsoft的*_s函数是不可移植的,我通常使用等效的C89/C99函数并禁用弃用警告(#define _CRT_SECURE_NO_DEPRECATE).

如果你坚持,你可以使用在没有的fopen()平台上委托的适配器函数(不一定是宏!)fopen_s(),但是你必须小心地映射errno_t返回代码的值errno.

errno_t fopen_s(FILE **f, const char *name, const char *mode) {
    errno_t ret = 0;
    assert(f);
    *f = fopen(name, mode);
    /* Can't be sure about 1-to-1 mapping of errno and MS' errno_t */
    if (!*f)
        ret = errno;
    return ret;
}
Run Code Online (Sandbox Code Playgroud)

但是,我没有看到如何fopen_s()更安全fopen(),所以我通常会寻求便携性.

  • 有趣的是,它们现在是C11的一部分(尽管在可选的附件K中) (9认同)
  • 顺便说一句,根据[this](http://en.cppreference.com/w/cpp/error/errno),** errno **“扩展为int类型的静态可修改左值,直到C ++ 11) ”和“扩展为int类型的线程本地可修改左值(自C ++ 11起)。” 因此,您的返回类型应为int。 (2认同)
  • *有趣的是,它们现在是 C11 的一部分* [微软的版本**不是**附件 K 的一部分](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1967 .htm):“Microsoft Visual Studio 实现了 API 的早期版本。但是,该实现并不完整,既不符合 C11 也不符合原始 TR 24731-1。...由于与规范存在大量偏差, Microsoft 的实现不能被认为是一致的或可移植的。” (2认同)

Raf*_*llo 9

如果您使用的是C11,fopen_s则是标准库:

http://en.cppreference.com/w/c/io/fopen

gcc你需要使用--std=C11参数.

  • 这个答案是错误的。[C11 标准的附录 K](https://port70.net/~nsz/c/c11/n1570.html#K) 中的 `fopen_s()` 和其他函数是可选的 [**K.2 范围* *,第 1 段](https://port70.net/~nsz/c/c11/n1570.html#K.2p1):“本附件指定了一系列可选扩展.​​.....”有效,截至 2019 年仅 Microsoft已实施附件 K 和 Microsoft 实施[“不能被视为符合或可移植”](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1967.htm)。 (5认同)
  • @Raffaello GCC 从未实施过附件 K,也永远不会实施。[给出一些原因](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1106.txt):“让我们投票反对该提案。这是有争议的,可以说会导致更多错误软件,并不反映社区的共识。” (2认同)

Jic*_*hao 6

在C/C++代码中,

#ifdef __unix
#define fopen_s(pFile,filename,mode) ((*(pFile))=fopen((filename),(mode)))==NULL
#endif
Run Code Online (Sandbox Code Playgroud)

在Makefile中

CFLAGS += -D'fopen_s(pFile,filename,mode)=((*(pFile))=fopen((filename),(mode)))==NULL'
Run Code Online (Sandbox Code Playgroud)

注意,成功时fopen_s返回0而fopen返回非零文件指针.因此有必要在宏的末尾添加"== NULL",例如:

if (fopen_s(&pFile,filename,"r")) perror("cannot open file");
Run Code Online (Sandbox Code Playgroud)

  • 如果“fopen()”失败,您错过了“fopen_s()”返回“errno”的部分。 (2认同)