我正在将一个简单的socket
客户端程序从Linux迁移到Windows(VS2012)。该计划使用常规的close
,read
和write
函数。
在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
和_close
,read
和_read
,write
和_write
之间的真正区别是什么?
只是更改为下划线版本会保留相同的行为吗?
答案 0 :(得分:2)
功能的POSIX名称仅保证在真正的POSIX系统上运行。 VisualC ++实现POSIX名称以帮助移植代码,但ISO标准使用下划线前缀名称。
POSIX可以被认为是“Unix平台API” - 严格来说它完全不同于C和C ++标准库(表面上是平台中立的[1]),因此POSIX的名称就像{ {1}},close
和write
完全有效 - 但仅限于他们的平台。
ISO版本使用下划线前缀,因为C ++标准声明(What are the rules about using an underscore in a C++ identifier?):
以下划线开头的每个名称都保留给实现,以用作全局命名空间中的名称
这个想法是用户应用程序代码可能想要自己使用read
和close
(因为它们非常具体),但是如果你使用相同的名称导入库你不能自己使用它们,否则你会收到名称冲突错误。
不幸的是,下划线前缀的规则只有在各种API和库已经根深蒂固之后很久才会出现,例如POSIX和Win32 - 所以现在我们留下了write
的丑陋混合。
[1]案例分析:直到最近(即过去几年),没有标准的方法来枚举C或C ++中的文件和目录,您总是需要使用特定于平台的API - 部分原因是因为C在某些从未支持过分层文件系统的计算机之前,例如最初的Macintosh。
答案 1 :(得分:2)
哇,这些都是搞笑的消息。干得好,微软。在VS2012中编译时,我收到以下警告
他们似乎暗示_close
,_read
和_write
在某种程度上是ISO C ++的功能。
他们不是!
close
和_close
,read
和_read
,write
和_write
之间的真正区别是什么?
Microsoft显然重新实现了POSIX函数close
,read
和write
。不同之处在于,重新实现时,他们选择使用前导下划线重命名这些函数,因为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_]*
命名空间的标识符,例如CreateWindow
和WaitForSingleObject
。
如果close
不符合“符合ISO C ++标准”,那么这些都不是!
实际上,ISO C和C ++允许实现者在普通命名空间中使用其他名称函数,例如close
或WaitForSingleObject
。像_close
这样的名称仅符合未来ISO C或C ++标准不可能使用它的意义。但实际上,对于任何主要API(如POSIX或Windows)的标识符也是如此。
如果你是系统API世界中的小玩家,并且你给一个函数一些简短的名字(也就是说,一个英文字典单词),即使它现在不与ISO C冲突,一个未来标准可以运行其众所周知的推土机。 POSIX功能没有发生这种情况的危险。