为什么不打开 char 值达到 case 0xC2?

Why doesn't switching on a char value reach case 0xC2?

在下面的代码中发现了一个错误,它解析 C-string 并且应该检测 UTF8 字符:

char* pTmp = ...;
...
switch (*pTmp)
{
    case 'o':
    {
        ...     // works fine
        break;
    }   
    case 0xC2:
    {
        ...     // never gets triggered
        break;
    }
}

然而 case 0xC2: 从未被触发。

我的假设是 0xC2 被认为是 int,因此 194 大于 127,char 数据类型的最大值。所以-62 != 194

或者这里可能有一些溢出或整数提升。

写入 switch ((unsigned char)*pTmp) 解决了这个问题。

但我想澄清一下这里到底发生了什么以及应用了哪些规则。

我也愿意更改标题,只是没有更好的想法。

我在添加 -Wall here

时得到了这个
warning: case label value exceeds maximum value for type [-Wswitch-outside-range]
   14 |             case 0xC2:

所以是的,你的推理是正确的。

Is char signed?

如果 char 具有与 signed charunsinged char 相同的范围,则它是特定于实现的。在 OP 的情况下,char 的范围是 [-128 ... 127],因此 case 0xC2: 永远不会匹配。


But I would like to clarify what is really going on here and what rules are applied.

C 标准库字符串函数有许多 char * 参数,但这些库函数在内部表现 就好像 它们指向 unsigned char数据

For all functions in this subclause, each character shall be interpreted as if it had the type unsigned char (and therefore every possible object representation is valid and has a different value). C17dr § 7.24.1 3

为了与之匹配,OP 的代码也应该这样做。这样做还将允许 *upTmp 可能匹配 0xC2.

char* pTmp = ...;
unsigned char* upTmp = ( unsigned char*) pTmp;

switch (*upTmp)

   case 0xC2:

替代使用十六进制常量 0xC2,使用字符常量'\xC2'来匹配范围char 个。 .


[迂腐]

"switch ((unsigned char)*pTmp) 解决了这个问题。" - 已经足够接近了。

此“修复”适用于带符号 char 的 2 补码,以及定义 char 的实现与 unsigned char.

匹配时

对于 char 有符号而不是 2 的补码的其余所有但不存在的情况,修复是错误的,因为字符应该通过 unsigned char * 访问,否则使用错误的值。

switch (*(unsigned char *)pTmp) 在所有情况下都能正常工作。