在 MSVC++ 中,有一个函数 strcmpi 用于不区分大小写的 C 字符串比较。
当您尝试使用它时,它就会出现,
从 Visual C++ 2005 开始,已弃用此 POSIX 函数。请改用符合 ISO C++ 的 _stricmp。
我不明白的是为什么 ISO 不希望 MSVC++ 使用 strcmpi,为什么 _stricmp 是首选方式,为什么他们要费心重命名该函数,以及以下划线开头的函数如何符合 ISO 标准。我知道这一切一定有一个原因,我怀疑它是因为 strcmpi 是非标准的,也许 ISO 希望非标准扩展以 _下划线开头?
ISO C 保留某些标识符以供将来扩展(请参阅此处),包括以“str”开头的任何标识符。
IMNSHO,这是微软的说法“不要将 Unix 软件放在 Windows 机器上”。这个问题有几个令人沮丧的方面:
strcmpi()
不是 POSIX 函数 - 相关函数在 <strings.h>
中定义,并称为 strcasecmp()
等。也就是说,GCC 工具链对某些功能有点不稳定 -
mktemp()
等人。然而,尽管有警告(这是有道理的),它仍然可以成功编译和链接。
我注意到 MSVC 的帽子里也有一只蜜蜂关于
snprintf()
等人。如果它们的函数符合 C99 标准(以及编译器的其余部分),那么永远不会有任何溢出风险 - 该标准要求 null 终止,这与 Microsoft 的声明相反。
我还没有找到一个真正好的解决方案来解决这个问题——我不确定是否有解决方案。一种可能性是创建一个标头(或一组标头)以将所有实际的 POSIX 名称映射到 Microsoft 对它们的误解。另一个方法是创建一个具有正确 POSIX 名称的简单函数库,每个函数都调用 Microsoft 版本的名称(为您提供大量四行函数的集合 - 声明符行、左大括号、右大括号和调用 POSIX 函数名称的 Microsoft 变体的 return 语句。
有趣的是,Microsoft API 调用也污染了用户的名称空间,但却没有被弃用或重命名。
以下划线和小写字母开头的名称如果在全局命名空间中声明,则由 C++ 标准保留用于 C++ 实现。这可以防止它们与您自己的代码中的相似名称发生冲突,您自己的代码不得使用此命名约定。
strcmpi
在 Visual C++ 2008 中完全消失,因此如果您打算升级,您一定要注意弃用。
_ 并不使函数成为 ISO 标准,只是随着语言的发展,以 _ 开头的函数添加起来更安全,因为这是为语言保留的命名空间部分之一。
根据 Microsoft 的
_stricmp
文档,听起来 strcmpi
有一些做法会导致一些不直观的排序(包括标准化为小写而不是简单地将大小写视为无关)。听起来 _stricmp
需要付出更多的努力才能做到人们自然期望的事情。
我维护 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