MSVC编译器说不推荐fopen()
,建议使用fopen_s()
。
有没有办法使用fopen_s()
并仍然可移植?
#define
的任何想法?
答案 0 :(得分:26)
Microsoft的*_s
函数不可移植,我通常使用等效的C89 / C99函数并禁用弃用警告(#define _CRT_SECURE_NO_DEPRECATE
)。
如果你坚持,你可以使用在没有fopen()
的平台上委派fopen_s()
的适配器功能(不一定是宏!),但你必须小心映射{的值{1}}从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;
}
比fopen_s()
更安全,所以我通常会寻求便携性。
答案 1 :(得分:10)
答案 2 :(得分:7)
在C / C ++代码中,
#ifdef __unix
#define fopen_s(pFile,filename,mode) ((*(pFile))=fopen((filename),(mode)))==NULL
#endif
在Makefile中
CFLAGS += -D'fopen_s(pFile,filename,mode)=((*(pFile))=fopen((filename),(mode)))==NULL'
注意成功时fopen_s返回0而fopen返回非零文件指针。因此,有必要在宏的末尾添加“== NULL”,例如:
if (fopen_s(&pFile,filename,"r")) perror("cannot open file");
答案 3 :(得分:2)
Microsoft的许多安全功能都包含在C11标准的附录K中,但它没有得到广泛支持,因此可移植性仍然是一个问题。在某些应用中需要提高安全性;也许这种支持将来会有所改善。
我过去,我是这样做的:
#define fopen_s(fp, fmt, mode) *(fp)=fopen( (fmt), (mode))
宏很简单直接,对于快速和脏的东西都足够好,但它不能提供fopen_s的异常行为,并且它不会提供真正的fopen_s函数的安全性。 / p> 上面的@Alex B&#39功能方法部分地再现了失败时的正确行为;他返回errno(= EINVAL)。他的方法可以通过生成无效参数异常进一步扩展,以更充分地再现fopen_s的行为。
答案 4 :(得分:0)
根据https://en.cppreference.com/w/c/io/fopen 可以在stdc库上启用* _s功能
”“与所有边界检查函数一样,只有在实现中定义了 STDC_LIB_EXT1 并且用户将 STDC_WANT_LIB_EXT1 定义为整数常量时,才能保证fopen_s可用。 1包括stdio.h。”
答案 5 :(得分:0)
#define fopen_s(fp, fmt, mode) ({\
*(fp)=fopen( (fmt), (mode));\
(*(fp) ) ? 0:errno;\
})