为啥 getcwd() 不符合 ISO C++ 标准?

Posted

技术标签:

【中文标题】为啥 getcwd() 不符合 ISO C++ 标准?【英文标题】:Why is getcwd() not ISO C++ compliant?为什么 getcwd() 不符合 ISO C++ 标准? 【发布时间】:2009-03-15 12:07:58 【问题描述】:

This MSDN article 声明 getcwd() 已被弃用,应改用与 ISO C++ 兼容的 _getcwd,这就提出了一个问题:是什么让 getcwd() 不符合 ISO 标准?

【问题讨论】:

【参考方案1】:

对此有一个good discussion。 P.J. Plauger 回答这个问题

我是那个在 1983 年坚持认为空间 C 程序可用的名称被划分为:

a)程序员的利益由实现定义的那些(例如 printf)b) 保留给程序员的那些(例如 foo) c) 为实现保留的那些(例如 _unlink)

即使在那时我们就知道“实施”过于单一—— 通常不止一个来源提供了一些实现—— 但那是我们当时能做的最好的事情。标准 C++ 引入了命名空间来提供帮助,但他们只实现了 他们既定目标的一小部分。 (这就是当你 标准化纸老虎。)

在这种特殊情况下,Posix 提供了一个类别 (a) 名称的列表 (例如取消链接)您应该在何时且仅当您 包括某些标题。由于 C 标准从 Unix,它与 Posix 的来源相同,其中一些标头 历史重叠。尽管如此,编译器警告应该有 某种方式考虑是否支持的环境 是“纯”标准 C++(柏拉图式的理想)还是混合的 C/C++/Posix 环境。微软目前帮助我们穷人的尝试 程序员没有考虑到这一点。它坚持治疗 unlink 作为类别 (b) 名称,这是短视的。

好吧,GCC 不会在严格的 C 模式下声明 POSIX 名称,至少(尽管它仍然在 C++ 模式下如此):

#include <stdio.h>

int main() 
    &fdopen;
    return 0;

使用-std=c99输出

test.c: In function 'main':
test.c:4: error: 'fdopen' undeclared (first use in this function)

您必须通过使用功能测试宏或未通过任何特定标准明确告诉它您是在混合 C/Posix 中操作。然后它将默认为gnu89,它假定一个混合环境(man feature_test_macros)。显然,MSVC 没有这种可能性。

【讨论】:

GCC 不声明 POSIX 甚至标准 C 名称。这就是 glibc 的工作。【参考方案2】:

标准中未指定的函数应该以下划线为前缀,以表明它们是特定于供应商的扩展或遵循非 ISO 标准。因此,这里的“合规性”是微软在这个特定函数的名称中添加下划线,因为它不是 ISO 标准的一部分。

【讨论】:

我认为没有人声称 Win32 API 兼容任何东西。如果您在 VC++ 中禁用语言扩展,windows.h 甚至不会编译。 :) 令人困惑的是,他们这样做是为了 posix 函数,而这些函数也不在标准 C 头文件中。 Windows API 不是 C 或 C++ 运行时库的一部分。 @Stuart - 这并不令人困惑......打破 POSIX 似乎是他们的作案手法。鼓励开发人员改用 Win32 API 对 Microsoft 是有益的。【参考方案3】:

正如其他人已经指出的那样,getcwd 不包含在 ISO C++ 中,而是 POSIX/IEEE Std 1003.1 的一部分。

Microsoft 已决定在其 C 标准库中包含一些最常用的 POSIX 函数(但在这些函数的前面加上下划线以从本质上阻止它们的使用)。

【讨论】:

【参考方案4】:

作为记录,getcwd() 并未被 ISO 弃用。它被微软“弃用”。 Microsoft 重写了许多 C 函数——通常考虑到更好的安全性(例如,字符串函数也采用max_length 参数)。然后他们让他们的编译器吐出这些警告,我认为这是虚假的,因为没有标准组弃用任何声明为弃用的函数。

【讨论】:

_CRT_SECURE_NO_WARNINGS 并忘记 :) 问题:“为什么 getcwd() 不符合 ISO 标准?/这篇 MSDN 文章指出 getcwd() 已被弃用......”答案:“getcwd() 未被弃用;微软正在吐槽带有“已弃用”的奇怪定义的警告。”这怎么不回答问题?我以什么方式要求澄清? getcwd() 也被 GNU 弃用。请参阅手册页“出于可移植性和安全原因,不推荐使用 getwd()。” @BjörnLindqvist:根据man7.org/linux/man-pages/man3/getcwd.3.html(和您的评论),GNU 调用getwd() 已弃用,但也说“改用getcwd()”。 (在“符合”部分)。另外,到目前为止,Open Group 还没有弃用 getcwd() ( pubs.opengroup.org/onlinepubs/9699919799/functions/getcwd.html )。【参考方案5】:

要添加到 Dan Olson 的帖子:请参阅 MSDN 上的 ANSI C Compliance 页面

Microsoft 特定函数和全局变量的名称以下划线开头。这些名称只能在您的代码范围内本地覆盖。例如,当您包含 Microsoft 运行时头文件时,您仍然可以通过声明同名的局部变量来本地覆盖名为 _open 的 Microsoft 特定函数。但是,您不能将此名称用于您自己的全局函数或全局变量。

【讨论】:

【参考方案6】:

据我所知,getcwd() 从未成为 ISO 标准 C++ 的一部分。 _getcwd() 绝对不是,因为标准名称不会以下划线开头。

事实上,MSDN 文章链接到一个手册页,说明它是在 direct.h 中声明的,它不是标准 C++ 头文件。这篇文章在我看来是假的。

【讨论】:

【参考方案7】:

MSDN 文章对于普通人通过快速阅读得出的结论有些令人困惑(如果他们不以非常仔细的律师眼光阅读)。

MSDN 文章所说的是:getcwd() 不符合 ISO C++ 标准。为了遵守函数命名的 ISO C++ 标准(这是 getcwd 违反的),微软在函数的前面正确地放了一个 _,所以同样的函数变成了 _getcwd()。这是符合 ISO C++ 的函数命名方式,因为 getcwd() 和 _getcwd() 不是 ISO C++ 标准函数,而是 Microsoft(供应商)特定或实现特定的函数。

这篇文章没有说明获取工作目录的 C++ ISO 标准调用是什么……尽管人们往往一眼就能读到。

【讨论】:

以上是关于为啥 getcwd() 不符合 ISO C++ 标准?的主要内容,如果未能解决你的问题,请参考以下文章

为啥visualstudio2008中文版.iso这个文件这么大呢?

stl中vector中erase后迭代器为啥会失效

判断下列事实是不是有不符合项,其违背了ISO9001:2000中的哪个条款,并简述其理由.

RFID阅读器标准

为啥从网上下不了centos6.6iso?

为啥从字符串常量转换为 'char*' 在 C 中有效但在 C++ 中无效