为什么不打开 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 char
或 unsinged 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)
在所有情况下都能正常工作。
在下面的代码中发现了一个错误,它解析 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 char
或 unsinged 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)
在所有情况下都能正常工作。