您的源代码使用 Visual C++ 11.0(Visual Studio 2012 附带的编译器)编译时甚至没有警告。
Intellisense 使用自己的规则,并不总是可靠的。
也就是说,您对除原始 7 位 ASCII 之外的所有字符集使用的isspace
是未定义行为。这意味着您从中获得的高度赞成的答案只是胡说八道(这不足为奇)。您需要将参数转换为(C 库的)isspace
以unsigned char
避免负值和 UB。
C99 §7.4/1(来自 N869 草案):
头文件<ctype.h>
声明了几个对测试和映射字符有用的函数。在所有情况下,参数都是 an int
,其值应表示为 anunsigned char
或应等于宏的值EOF
。如果参数有任何其他值,则行为未定义。
包装 C 函数的一种简单方法是
bool isSpace( char const c )
{
typedef unsigned char UChar;
return !!::isspace( UChar( c ) );
}
为什么typedef
?
当您已经拥有这样的 时,它使代码更容易适应typedef
,这并不少见;
它使代码更清晰;和
它避免了 C 语法转换,从而在通过正则表达式或其他模式匹配进行搜索时避免误报。
但是,为什么!!
(否定运算符的双重应用)?考虑到从to的自动隐式转换?而且,如果有人绝对认为转换应该是明确的,那不应该是 a ,而不是?int
bool
static_cast
!!
好吧,!!
避免了来自 Visual C++ 编译器的愚蠢警告,
“警告 C4800: 'int' : 强制值 bool 'true' 或 'false' (性能警告)”
并且 astatic_cast
不会停止该警告。最好的做法是消除该警告,并且由于 Visual C++ 是最常用系统(即 Windows)上的主要 C++ 编译器,因此最好在所有可移植的代码中执行此操作。
哦,好的,但是,既然函数无论如何都必须被包装,那么……为什么要使用旧的 C 库isspace
(单参数)函数,而<locale>
头文件提供了一个更灵活的 C++(两个参数)isspace
函数?
嗯,首先,旧的 Cisspace
函数是问题中使用的函数,所以这就是这个答案中讨论的函数。我专注于讨论如何不错误地执行此操作,即如何避免未定义的行为。讨论如何正确地做这件事会把它带到一个完全不同的层次。
但是在实践中,可以认为同名的 C++ 级函数已被破坏,因为直到最近使用 g++ 编译器(甚至可能使用 g++ 4.7.2,我最近都没有检查过)只有 C 语言环境机制在 Windows 中有效,而 C++ 一级没有。它可能已经修复,因为 g++ 现在支持宽流,我不知道。无论如何,那里的 C 库isspace
函数,除了在实践中更便携和通常在 Windows 中工作之外,还更简单,我相信,更高效(尽管为了提高效率,如果它被认为很重要,应该总是 MEASURE!)。
感谢 James Kanze 在评论中提出(基本上)上述问题。