close vs _close,read vs _read,write vs _write - 有什么区别?

时间:2016-04-05 23:18:01

标签: c++ sockets visual-studio-2012

我正在将一个简单的socket客户端程序从Linux迁移到Windows(VS2012)。该计划使用常规的closereadwrite函数。

在VS2012中编译时,我收到以下警告:

warning C4996: 'close': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _close

warning C4996: 'write': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _write

warning C4996: 'read': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _read

解决方案很简单 - 只需添加底层代码 - 但是......

close_closeread_readwrite_write之间的真正区别是什么?

只是更改为下划线版本会保留相同的行为吗?

3 个答案:

答案 0 :(得分:2)

功能的POSIX名称仅保证在真正的POSIX系统上运行。 VisualC ++实现POSIX名称以帮助移植代码,但ISO标准使用下划线前缀名称。

POSIX可以被认为是“Unix平台API” - 严格来说它完全不同于C和C ++标准库(表面上是平台中立的[1]),因此POSIX的名称就像{ {1}},closewrite完全有效 - 但仅限于他们的平台。

ISO版本使用下划线前缀,因为C ++标准声明(What are the rules about using an underscore in a C++ identifier?):

  

以下划线开头的每个名称都保留给实现,以用作全局命名空间中的名称

这个想法是用户应用程序代码可能想要自己使用readclose(因为它们非常具体),但是如果你使用相同的名称导入库你不能自己使用它们,否则你会收到名称冲突错误。

不幸的是,下划线前缀的规则只有在各种API和库已经根深蒂固之后很久才会出现,例如POSIX和Win32 - 所以现在我们留下了write的丑陋混合。

[1]案例分析:直到最近(即过去几年),没有标准的方法来枚举C或C ++中的文件和目录,您总是需要使用特定于平台的API - 部分原因是因为C在某些从未支持过分层文件系统的计算机之前,例如最初的Macintosh。

答案 1 :(得分:2)

  

在VS2012中编译时,我收到以下警告

哇,这些都是搞笑的消息。干得好,微软。

他们似乎暗示_close_read_write在某种程度上是ISO C ++的功能。
他们不是!

  

close_closeread_readwrite_write之间的真正区别是什么?

Microsoft显然重新实现了POSIX函数closereadwrite。不同之处在于,重新实现时,他们选择使用前导下划线重命名这些函数,因为ISO C ++标准表明,前导下划线是实现(即Visual Studio)应该用于内部/内置函数的内容。

  

只是更改为下划线版本会保留相同的行为吗?

我不会在这里列举各种潜在的差异。当然,有关这些功能如何工作以及如何使用它们的完整信息,请阅读其文档。但是,直接的答案是假设行为与类似命名的POSIX函数的行为相同。

答案 2 :(得分:2)

错误信息是政治声明,而不是真实的事实。

由于_close声称是“ISO C ++符合”,因此暗示POSIX close命名 符合ISO C ++标准。

这是完全垃圾。

带有下划线的名称只是微软几十年来在其库中实现模仿POSIX子集的方式。 (使用扩展程序,例如_spawn*函数系列,以弥补fork的缺失。

这些名称符合ISO C和C ++,因为它们仅限于保留的命名空间。如果,程序员使用_close之类的标识符作为外部名称,则行为未定义。但这并不意味着语言实现者将这些标识符用于其公共API是一个好主意。它们对内部(可能是未记录的)标识符很有用。微软做了一个令人遗憾的选择,一次创建一些带有丑陋名字的API,后来制作了一个编译器错误消息来追溯它。

但是,看看,Windows API充满了不仅限于_[a-zA-Z0-9_]*命名空间的标识符,例如CreateWindowWaitForSingleObject

如果close不符合“符合ISO C ++标准”,那么这些都不是!

实际上,ISO C和C ++允许实现者在普通命名空间中使用其他名称函数,例如closeWaitForSingleObject。像_close这样的名称仅符合未来ISO C或C ++标准不可能使用它的意义。但实际上,对于任何主要API(如POSIX或Windows)的标识符也是如此。

如果你是系统API世界中的小玩家,并且你给一个函数一些简短的名字(也就是说,一个英文字典单词),即使它现在不与ISO C冲突,一个未来标准可以运行其众所周知的推土机。 POSIX功能没有发生这种情况的危险。