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

17

这篇MSDN文章指出,getcwd()已被废弃,应该使用符合ISO C++的_getcwd。这引出了一个问题:是什么导致getcwd()不符合ISO标准?

7个回答

26

关于这个问题有一个很好的讨论P.J. Plauger在其中回答了这个问题。

我就是1983年坚持认为C程序中的名称空间应该被分为以下三类的那个家伙:

a)由实现定义、对程序员有用的名称(例如printf)
b)保留给程序员使用的名称(例如foo)
c)保留给实现使用的名称(例如_unlink)

我们当时知道,“实现”太过庞大 - - 往往不止一个源提供了实现的一部分 - - 但那是我们当时能做到的最好的。标准C ++引入了命名空间来帮助,但它们只实现了部分目标。(当你把一个纸老虎标准化时就会发生这种情况。)

在这个特定的情况下,Posix提供了一个类别(a)名称列表(如unlink),只有在包含某些头文件时才定义。由于C标准从Unix中窃取了它的头文件,并且与Posix使用了相同的源,因此这些头文件在历史上有重叠之处。 然而,编译器警告应该有一种方法来考虑支持的环境是“纯”标准C ++(柏拉图式理想)还是混合C / C ++ / Posix环境。微软目前帮助我们这些可怜的程序员的尝试未能考虑到这一点。它坚持将unlink视为类别(b)名称,这是近视眼的。

好吧,在严格的C模式下,GCC不会声明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没有这个可能性。


3
GCC不声明POSIX甚至标准C名称,这是glibc的工作。 - Potatoswatter

20

标准中未指定的函数应该以下划线开头,表示它们是供应商特定扩展或遵循非ISO标准。 因此,此处的“兼容性”是指Microsoft需要在该特定函数的名称前加下划线,因为它不是ISO标准的一部分。


4
我不认为有人曾声称Win32 API符合任何规范。如果在VC++中禁用语言扩展,windows.h甚至都无法编译 :)。 - jalf
1
令人困惑的是,他们对不在标准C头文件中的posix函数也进行了这样的操作。 - Stuart P. Bentley
7
Windows API 不属于 C 或 C++ 运行时库。 - Michael Burr
13
@Stuart - 这不会让人感到困惑...打破 POSIX 似乎是他们的作法。鼓励开发者使用 Win32 APIs 对于微软来说是有益的。 - Tom

5

应该说明的是,getcwd()函数没有被ISO弃用,而是被微软“弃用”了。微软重写了许多C函数——通常考虑了一些更好的安全性(例如,字符串函数也需要一个max_length参数)。然后他们让编译器输出这些警告,但我认为这些警告是没必要的,因为任何标准组织都没有弃用任何声明为弃用的函数。


9
_CRT_SECURE_NO_WARNINGS 是一个预处理指令,用于告诉编译器忽略某些安全性错误。 "forget :)" 可能是一种幽默或轻松的方式来表示不再需要担心这个问题了。 - Nick Van Brunt
问题:“为什么getcwd()不符合ISO标准?/这篇MSDN文章指出getcwd()已经被弃用…”回答:“getcwd()并没有被弃用;微软只是以一种奇怪的‘弃用’定义来发出警告。”这个回答为什么不能回答问题?我在哪方面需要澄清? - Max Lybbert
getcwd() 也被 GNU 废弃了。请参阅手册页:“由于可移植性和安全原因,已弃用使用 getwd()。” - Björn Lindqvist
根据http://man7.org/linux/man-pages/man3/getcwd.3.html(以及您的评论),GNU称`getwd()`已被弃用,但也说“请改用`getcwd()`”(在“符合性”部分)。此外,到目前为止,Open Group尚未废弃getcwd()(http://pubs.opengroup.org/onlinepubs/9699919799/functions/getcwd.html)。 - Max Lybbert

4

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

微软决定将一些最常用的POSIX函数包含在其C标准库中(但使用下划线作为前缀以实质上阻止它们的使用)。


3
这篇MSDN文章有些令人困惑,如果快速阅读(不用非常小心地以律师的眼光来阅读),普通人会得出什么结论也不太清楚。
MSDN文章说的是:getcwd()不符合ISO C++标准。为了遵守ISO C++标准对函数命名的要求(这是getcwd违反的规定),Microsoft在函数前面加上了_,因此同一个函数变成了_getcwd()。这是ISO C++标准下命名函数的合规做法,因为getcwd()和_getcwd()不是ISO C++标准函数,而是Microsoft(供应商)特定或实现特定函数。
这篇文章没有说明ISO C++标准调用获取工作目录的方法...虽然这是人们快速浏览时候关注的内容。

3
据我所知,getcwd()从未成为ISO标准C++的一部分。_getcwd()肯定不是,因为标准名称不会以下划线开头。
实际上,MSDN文章链接到一个手册页面,该页面声明了它在direct.h中声明,这不是标准的C++头文件。我认为这篇文章是虚假的。

3
为了补充Dan Olson的帖子: 请参见MSDN上的 ANSI C Compliance页面。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接