2

我看到这三个功能都与打开文件有关。

打开

此 POSIX 函数已弃用。请改用符合 ISO C++ 标准的 _open。

_打开

打开一个文件。这些功能已被弃用,因为有更安全的版本可用;见_sopen_s,_wsopen_s。

开放

打开一个文件。这些执行附加参数验证和返回错误代码的函数的更安全版本可用;参见 fopen_s、_wfopen_s。

那么,为什么会有三个呢?什么时候用哪个?我认为 POSIX 很好,但为什么 MSDN 说不open推荐使用 POSIX 版本?是否有任何与前导下划线相关的命名约定,以便我可以根据它的第一个外观选择正确的函数?

当我查看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

加 1

似乎单个下划线前缀_XXX是微软的惯例。比如_DEBUG_CrtSetDbgFlag和前面提到的_open。引用MSDN的一些话:

在 Microsoft C++ 中,带有两个前导下划线的标识符保留用于编译器实现。因此,Microsoft 约定是在 Microsoft 特定关键字之前使用双下划线。这些词不能用作标识符名称。

默认情况下启用 Microsoft 扩展。为确保您的程序完全可移植,您可以在编译期间通过指定 ANSI 兼容的 /Za 命令行选项(为 ANSI 兼容性而编译)来禁用 Microsoft 扩展。执行此操作时,Microsoft 特定的关键字将被禁用。

启用 Microsoft 扩展后,您可以在程序中使用 Microsoft 特定的关键字。为了符合 ANSI,这些关键字以双下划线开头。为了向后兼容,支持除 __except、__finally、__leave 和 __try 之外的所有双下划线关键字的单下划线版本。此外,__cdecl 可以不带前导下划线。

__asm 关键字替换了 C++ asm 语法。asm 保留用于与其他 C++ 实现兼容,但未实现。使用 __asm。

__based 关键字对 32 位和 64 位目标编译的用途有限。

虽然根据上面的引用,__int64应该_int64都可以工作,但是 Visual Studio 没有为_int64. 但_int64也可以编译。

添加 2

snprintf() 和 _snprintf()

4

1 回答 1

4
  • 就 Windows 而言,打开文件的功能是CreateFile. 这将返回 aHANDLE并且由 Kernel32.dll 提供,而不是由 Visual Studio 提供。HANDLE可以传递给其他 Windows API 函数。

  • 和函数是 POSIX 兼容函数_openopen可帮助您在 Windows 上编译为 POSIX(Linux、macOS、BSD、Solaris 等)编写的程序。这些函数由 Visual Studio 的 C 运行时定义,并且可能在CreateFile内部调用。该函数的 POSIX 名称是open,但此处的函数定义为_open以防您已经open在代码中定义了一个命名的函数。该函数返回一个int可以传递给其他 POSIX 函数的值。在 Windows 上,这个接口是 Visual Studio 提供的兼容 API,但在 Linux 和 macOS 上,这个接口是操作系统的直接接口,就像HANDLE在 Windows 上一样。

  • fopen函数是 C 标准的一部分。它由 Visual Studio 的 C 运行时定义,并且可能在CreateFile内部调用。它返回一个FILE *可以传递给 C 标准定义的其他函数的函数。

因此,总结一下选项:

  • 如果你需要直接使用 Windows API,比如调用GetFileInformationByHandleor CreateFileMapping,你需要一个HANDLE并且你应该调用CreateFile来打开文件。

  • 如果您有一个已经为 POSIX 系统编写的程序,那么您可以使用open它来更轻松地将您的程序移植到 Windows。如果您只是为 Windows 编写代码,则使用此界面没有任何优势。

  • 如果你的程序只需要进行基本的文件操作,如打开、读取和写入,那么fopen就足够了,它也可以在其他系统上运行。AFILE *可以(并且通常是)由您的应用程序缓冲,并支持方便的操作,如fprintffscanffgets. 如果你想调用fgets一个返回的文件,CreateFile或者open你必须自己写。

可以将文件句柄从一个 API 转换为另一个,但您必须注意所有权问题。“所有权”并不是一个真正的技术概念,它只是描述了谁负责管理对象的状态,并且您希望避免破坏您不拥有的对象,并避免同一对象有多个所有者。

  • 对于 Windows API,您可以使用从 a_open_osfhandle()创建一个,并从. 但是,在这两种情况下,句柄都将归.FILE *HANDLE_get_osfhandle()HANDLEFILE *FILE *

  • 对于 POSIX API,您可以使用从文件描述符fdopen()创建 a ,并且可以使用从. 同样,在这两种情况下,文件都归.FILE *intfileno()intFILE *FILE *

请注意,Windows 文件wchar_t名是char.

如果您使用像 MinGW 这样的不同 C 运行时,或者如果您使用适用于 Linux 的 Windows 子系统,情况会有所不同。

于 2017-06-28T02:57:40.427 回答