我发现这三个函数都与打开文件有关。
open https://msdn.microsoft.com/en-us/library/ms235491(v=vs.120).aspx:
此 POSIX 函数已弃用。使用符合 ISO C++ 标准的 _open
反而。
_open https://msdn.microsoft.com/en-us/library/z0kc8e3z(v=vs.120).aspx:
打开一个文件。这些函数已被弃用,因为更安全
版本可用;参见 _sopen_s、_wsopen_s。
fopen https://msdn.microsoft.com/en-us/library/yeby3zcb(v=vs.120).aspx:
打开一个文件。这些功能的更安全版本执行
提供额外的参数验证和返回错误代码;
参见 fopen_s、_wfopen_s。
那么,为什么是他们三个呢?什么时候用哪个?我认为 POSIX 很好,但为什么 MSDN 说 POSIX 版本open
已弃用?还有有没有命名约定与前导下划线相关,这样我就可以根据它的第一眼选择正确的函数?
当我正在调查ACPICA代码 https://github.com/acpica/acpica/,我看到下面的代码:
看来_XXX
版本可以禁用一些MS 语言扩展,这些扩展到底是什么?
/*
* Map low I/O functions for MS. This allows us to disable MS language
* extensions for maximum portability.
*/
#define open _open
#define read _read
#define write _write
#define close _close
#define stat _stat
#define fstat _fstat
#define mkdir _mkdir
#define snprintf _snprintf
#if _MSC_VER <= 1200 /* Versions below VC++ 6 */
#define vsnprintf _vsnprintf
#endif
#define O_RDONLY _O_RDONLY
#define O_BINARY _O_BINARY
#define O_CREAT _O_CREAT
#define O_WRONLY _O_WRONLY
#define O_TRUNC _O_TRUNC
#define S_IREAD _S_IREAD
#define S_IWRITE _S_IWRITE
#define S_IFDIR _S_IFDIR
ADD 1
好像是单下划线前缀_XXX
是微软的约定。例如_DEBUG https://msdn.microsoft.com/en-us/library/0b98s6w8.aspx, _CrtSetDbgFlag https://msdn.microsoft.com/en-us/library/5at7yxcs.aspx,以及前面提到的_open https://msdn.microsoft.com/en-us/library/z0kc8e3z(v=vs.120).aspx。部分引述自MSDN https://msdn.microsoft.com/en-us/library/2e6a4at9.aspx:
在 Microsoft C++ 中,带有两个前导下划线的标识符是
保留用于编译器实现。因此,微软
约定是在 Microsoft 特定关键字之前加上 double
下划线。这些词不能用作标识符名称。
默认情况下启用 Microsoft 扩展。为确保您的
程序是完全可移植的,您可以通过以下方式禁用 Microsoft 扩展
指定 ANSI 兼容的 /Za 命令行选项(编译为
ANSI 兼容性)在编译期间。当你这样做时,
Microsoft 特定的关键字已禁用。
启用 Microsoft 扩展后,您可以使用
您的程序中的 Microsoft 特定关键字。为了符合 ANSI 标准,
这些关键字以双下划线。对于落后的
兼容性,单下划线所有的版本
双下划线关键字,除了 __except、__finally、__leave 和
支持 __try。此外,__cdecl 可以不带前导下划线。
__asm 关键字取代了 C++ asm 语法。 asm 保留用于
与其他 C++ 实现兼容,但未实现。使用
__asm。
__based 关键字对于 32 位和 64 位目标的用途有限
汇编。
虽然根据上面的引用,__int64
and _int64
应该都可以工作,但是 Visual Studio 不提供语法突出显示_int64
. But _int64
也可以编译。
ADD 2
snprintf() 和 _snprintf() https://stackoverflow.com/questions/11579095/why-in-msvc-we-have-snprintf-while-other-compilers-allows-snprintf