Visual c++ open()、_open()和fopen()在MSVC编译器方面有什么不同?

Visual c++ open()、_open()和fopen()在MSVC编译器方面有什么不同?,visual-c++,posix,clib,Visual C++,Posix,Clib,我看到这3个函数都与打开文件有关 : 此POSIX函数已被弃用。< /强>使用ISO C++一致性打开 相反 : 打开一个文件。这些函数不推荐使用,因为它们更安全 有版本可供选择;请参阅“打开”和“打开” : 打开一个文件。执行以下操作的这些功能的更安全版本 额外的参数验证和返回错误代码可用; 请参见fopen_s、\wfopen_s 那么,为什么有三个呢?什么时候用哪个?我认为POSIX很好,但是为什么MSDN说POSIX版本的open不受欢迎呢?是否有任何与前导下划线相关的命名约定,以便我

我看到这3个函数都与打开文件有关

:

<强>此POSIX函数已被弃用。< /强>使用ISO C++一致性打开 相反

:

打开一个文件。这些函数不推荐使用,因为它们更安全 有版本可供选择;请参阅“打开”和“打开”

:

打开一个文件。执行以下操作的这些功能的更安全版本 额外的参数验证和返回错误代码可用; 请参见fopen_s、\wfopen_s

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

当我查看时,我看到以下代码: 似乎
\u 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
/*
*映射MS的低I/O功能。这允许我们禁用MS语言
*最大可移植性的扩展。
*/
#定义open\u open
#定义读取\u读取
#定义写入
#定义关闭\u关闭
#定义stat\u stat
#定义fstat\u fstat
#定义mkdir\u mkdir
#定义snprintf\u snprintf
#如果MSC\u VER
  • 就Windows而言,打开文件的功能是。这将返回一个
    句柄
    ,由Kernel32.dll提供,而不是由Visual Studio提供。
    句柄可以传递给其他Windows API函数

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

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

因此,总结一下选项:

  • 如果需要直接使用Windows API,如调用
    GetFileInformationByHandle
    CreateFileMapping
    ,则需要一个
    HANDLE
    ,您可能应该调用
    CreateFile
    来打开文件

  • 如果您有一个已经为POSIX系统编写的程序,那么您可以使用
    open
    使您的程序更容易移植到Windows。如果您只为Windows编写,那么使用此界面没有任何好处

  • 如果您的程序只需要执行基本的文件操作,如打开、读取和写入,那么
    fopen
    就足够了,它也可以在其他系统上工作。
    文件*
    可以(通常是)由应用程序缓冲,并支持方便的操作,如
    fprintf
    fscanf
    fgets
    。如果要对
    CreateFile
    open
    返回的文件调用
    fgets
    ,则必须自己编写

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

  • 对于Windows API,您可以使用
    \u open\u osfhandle()
    句柄创建
    文件*
    ,并使用
    \u get\u osfhandle()
    文件*
    获取
    句柄。但是,在这两种情况下,句柄都将属于
    文件*

  • 对于POSIXAPI,可以使用
    fdopen()
    int
    文件描述符创建
    文件*
    ,也可以使用
    fileno()
    文件*
    获取
    int
    文件描述符。同样,在这两种情况下,文件都属于
    文件*

请注意,Windows文件名是
wchar\u t
的数组,而macOS/Linux/等文件名是
char
的数组,这使得可移植性变得复杂


如果使用像MinGW不同的C运行时,或者如果使用Windows子系统来处理Linux,情况就会不同。

你在C++中编译文件。您必须通过告诉VC以C的形式编译文件。
open()
在POSIX中并没有被弃用。windows似乎就是windows。。。他们不希望人们使用POSIX中的
open()
。假设MSVC不兼容POSIX。1)这与C无关,而是附加的库函数。2) 它们在这方面是正确的,因为
open
可能与用户名冲突<代码>\u open
使用实现保留名称。3)
open
是POSIX标准,所以如果您编写POSIX程序,请使用它。没有人使用MS extensions
\u open
,等等。4)对于C和POSIX标准,微软是一个非常糟糕的参考。大家都知道,他们不遵守标准(例如,MSVC从18年前开始就故意不遵守标准(C99)。事实上,他们甚至不保证完全遵守C90,iirc.5)。如果你用C编程,请使用符合标准的编译器,如gc