strcmpi被重命名为_strcmpi?

9
在MSVC++中,有一个用于不区分大小写的C字符串比较的函数strcmpi
当您尝试使用它时,会出现以下信息:
自Visual C++ 2005起,此POSIX函数已过时。请改用符合ISO C++标准的_stricmp。
我不明白的是,为什么ISO不希望MSVC++使用strcmpi,为什么_stricmp是首选方式,他们为什么要重命名该函数,以及一个以下划线开头的函数如何符合ISO标准。我知道这一定有原因,我怀疑是因为strcmpi是非标准的,也许ISO希望非标准扩展以_下划线开头?
5个回答

13

ISO C保留了某些标识符,以便于未来的扩展(请参阅此处),其中包括任何以“str”开头的内容。


ISO C 【§7.31 未来库方向】(http://port70.net/~nsz/c/c11/n1570.html#7.31)章节 【§7.31.13 字符串处理 <string.h>】(http://port70.net/~nsz/c/c11/n1570.html#7.31.13)指定:在 <string.h> 头文件的声明中,以 strmemwcs 开头且后跟小写字母的函数名称可以添加。这意味着 str_lower()strUpper() 等名称不受 C 标准保留,但 strequal() 是受保留的。 - Jonathan Leffler

10
在我看来,这是微软在表达“不要将Unix软件放在Windows机器上”的方式。问题有几个令人沮丧的方面:
  1. strcmpi() 不是 POSIX 函数 - 相关函数定义在 <strings.h> 中,并被称为 strcasecmp() 等等。
  2. 即使您明确请求支持 POSIX 函数,微软认为您可能不使用 POSIX 名称,而必须在前面加下划线。
  3. AFAIK,没有一种方式可以覆盖 MSVC 编译器对此问题的看法。
话虽如此,GCC 工具链对某些函数也有点抱怨 - 例如 mktemp() 等等。但是,尽管存在警告(这些警告是合理的),它确实可以成功编译和链接。
我注意到 MSVC 还对 snprintf() 等等有所挑剔。如果他们的函数符合 C99 标准(以及编译器的其余部分),那么就永远不会有溢出的风险 - 标准要求空终止,与 Microsoft 的说法相反。
我没有一个真正好的解决方案来解决这个问题 - 我不确定是否有。一个可能性是创建一个标头(或一组标头),将所有实际的 POSIX 名称映射到 Microsoft 对它们的错误解释。另一个选择是创建一个由简单函数组成的库,其中带有正确的 POSIX 名称,并将每个函数调用下传到 Microsoft 版本的名称(这将给您带来一个巨大的四行函数集合 - 声明器行、一对大括号、一个返回语句,调用 POSIX 函数名称的 Microsoft 变体)。
有趣的是,微软 API 调用还会污染用户的命名空间,但它们并没有被弃用或重命名。

4
说得好!同时,MSVC 坚持发出有关不安全库函数的警告并建议使用 *_s 变量名后缀,这也很烦人。 - JesperE
请注意,Visual Studio 2015现在具有符合至少C99的vsnprintf()等版本,以及(向后兼容且未更改的)_vsnprintf()版本。 - Jonathan Leffler

3
以下划线和小写字母开头的名称是C++标准保留给全局命名空间中的C++实现。这样可以避免它们与您自己代码中的相似名称发生冲突,因此您的代码不应使用此命名约定。

2

strcmpi在Visual C++ 2008中完全消失了,因此如果您打算升级,一定要注意其弃用。

下划线并不使函数符合ISO标准,只是以_开头的函数更安全,因为这是命名空间保留给语言使用的部分之一,可以随着语言的发展而添加。

根据Microsoft对_stricmp的文档,似乎strcmpi有一些实践会导致一些不直观的排序(包括将所有字符转换为小写字母而不是简单地将大小写视为不相关)。听起来_stricmp更加注重做到自然预期。


0

我保持 POSIX 兼容性的方法:

// Check if on MS compiler (newer than Visual Studio 2015)
#if ( _MSC_VER > 1900 )
// redefine the name
#ifndef stricmp
#define stricmp _stricmp
#endif
#endif // _MSC_VER

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