2

可能重复:
不推荐使用 getch

正如标题所说,这两种方法有什么区别?我是新手,所以我对它们的用法感到困惑......

4

2 回答 2

3

至少在我知道的实现中,函数本身没有区别。实际上,它们通常只是完全相同功能的两个不同名称。

至于有两个名字的原因:确实没有一个很好的名字。微软的某个人显然没有仔细阅读该标准的要求,并且基于对它的误解做出了一些相当……糟糕的决定。

首先,没有在标准标头中声明,因此更改名称并不是从1getch开始的真正必要的。其次,如果他们确实需要更改名称,那么无论如何都不对 - 为实现保留的名称以下划线开头(他们做得非常正确),然后是另一个下划线或大写字母(他们弄错了) . 换句话说,如果他们要更改名称,它应该是, 或,但至少就标准而言,它和 plain 一样糟糕_getch__getch_Getch_getchgetch

就它们之间的选择而言:我只是使用getch它并完成它。使用_getch实际上使您的代码(略微)不那么可移植——在大多数 Unix 系统上做同样的事情,你使用 curses,它包括一个函数来做(大部分)同样的工作——它的名字是getch. 因此,如果您曾经移植过您的代码,则需要更改包含的标头,但名称getch是少数几个实际上会继续工作的名称之一。如果您正在执行大量交互式 I/O,那么您可能不得不重写相当多的其他代码。


1好吧,反正也不应该。回到 16 位时代,Microsoft 的链接器有一个小问题,您必须向它传递一个额外的开关 ( /noe) 或您定义的名称之间的任何重复,而您正在链接的库中定义的名称会导致错误。所以,那时你必须通过一个额外的开关来获取链接代码,如果它使用与库中任何东西相同的名称,而不仅仅是一个标准名称。但这几乎是古老的历史。

于 2012-08-17T16:05:03.600 回答
3

微软 C 编译器的非常古老的实现提供的函数使用的名称与 POSIX/UNIX 世界中的名称相同和/或侵犯了用户的命名空间。请注意,其中一些是“侵权”,可能是在标准化发生之前(在 MS-DOS 时代)。

很久以前,Microsoft 决定将这些名称移动到为编译器实现保留的一组名称中。他们为图书馆里的许多名字都这样做了,即使严格来说他们可能不必这样做。似乎他们对所有非标准 C/C++ 的库名称都这样做了。请注意,这不适用于 SDK 中的名称 - 该组头文件和库位于编译器实现域之外,即使 SDK 与编译器一起分发也是如此。

为了与使用旧名称(没有下划线的程序)编写的程序兼容,Microsoft 提供了一个库 oldnames.lib,它实现了将旧名称(例如getch)链接到新名称 ( _getch) 的别名。这两个名称指的是完全相同的代码。因此,就使工作正常而言,您可以使用任一名称(尽管您可能需要设置您的项目以链接到oldnames.lib)。

如果您有使用旧名称的旧 Windows 代码,我认为最好只是链接oldnames.lib并完成。

对于新代码,我认为使用新名称(带下划线且不链接 oldnames.lib)可能会稍微好一些。旧名称已被 Microsoft 弃用,其他一切都相同的情况下,这可能会影响天平。而且,如果您最终将代码移植到 POSIX 系统或将 POSIX 代码移植到 Windows,则更有可能会提醒您注意可能需要注意的区域。这些函数可能看起来和大部分行为都类似于 POSIX 版本,但它们可能需要以稍微不同的方式使用 - 特别是在错误处理中。

或者,您可以尝试使用 PDCurses 之类的库,或者使用您自己的包装器来提供可移植性,具体取决于对您而言价值多少。或者,如果您真的希望在 Windows 上具有 POSIX 可移植性,Cygwin 可能是一种选择(Unix 服务仍然存在吗?)。

MSVC 和 POSIX 函数具有相同/相似名称的细微差别的一些示例:

  • getch()在 Windows 上永远不会回显字符,总是阻塞直到有输入,需要多次调用才能读取某些键,并且不能返回错误。这些行为与 POSIX 不同。
  • ungetch()在 Windows 上返回传入或EOF出错的字符。在 POSIX 上,它返回OKor ERR
于 2012-08-18T06:58:04.663 回答