switch-case 如何处理“case"中的常量值?
假设我们有
typedef unsigned char BYTE;#define CPUTYPE_INVALID ((BYTE)-1)
switch 语句会命中哪种情况?
BYTE m_CPUTYPE;m_CPUTYPE = 0xff;开关(m_CPUTYPE){案例 255:cout <<击中 1";情况1:cout <<击中 2";案例 CPUTYPE_INVALID:cout <<命中 3";休息;默认:cout <<没有命中";休息;}
那会是什么结果呢?请详细说明.
解决方案警告
您的代码可能格式错误,如果我们正在处理一个平台,其中
unsigned char
由 8 位组成(这是最常见的情况),它绝对是.
<小时>
标准是怎么说的?
标准中规定两个case常量在转换为switch条件使用的整数类型后不具有相同的值.
<块引用>6.4.2p2
switch
语句 [stmt.switch]
条件应为整数类型、枚举类型或类类型.如果是类类型,则条件在上下文中隐式转换(第 4 条)为整数或枚举类型.进行整体促销.switch
语句中的任何语句都可以用一个或多个 case 标签进行标记,如下所示:
case 常量表达式:
其中 constant-expression 应是转换条件的提升类型的转换常量表达式 (5.19).同一 switch 中的任何两个 case 常量在转换为 switch 条件的提升类型后不应具有相同的值.
这意味着 if 整数类型由 m_CPUTYPE
类型的整数提升产生,处理 static_cast
和 static_cast<int>(255)
是相同的值.. 片段格式不正确.
那么,我安全吗?
整数提升是一种将一个整数类型提升为另一种类型的方法,如果在处理两个可能属于不同类型的整数值时,为了便于实现和逻辑而需要这样做.p><块引用>
4.5
整体促销 [conv.prom]
除 bool、char16_t、char32_t 或 wchar_t 之外的整数类型的纯右值,其整数转换等级 (4.13) 小于 int
的等级,可以转换为 int
如果 int
可以表示源类型的所有值;否则,源纯右值可以转换为 unsigned int
类型的纯右值.
标准中规定unsigned char
的rank小于int
,这样切换条件的类型为int
,进一步表示;static_cast<int>(-1) != static_cast<int>(255)
.
但是,在大多数平台上,unsigned char 的最大值是 255
,这意味着 (BYTE)-1)
将产生unsigned char,其值为 255
.这意味着 255 == CPUTYPE_INVALID
.
switch (m_CPUTYPE) {案例 255://(A)cout<<"命中 1";情况1:cout<<"命中 2";case CPUTYPE_INVALID://(B), 与 (A) 相同的值cout<<"命中 3";休息;默认:cout<<"没有命中";休息;}
您有两个大小写常量,转换后产生相同的值:您的代码格式错误.
Let's say we have
typedef unsigned char BYTE;
#define CPUTYPE_INVALID ((BYTE)-1)
Which case will the switch statement hit?
BYTE m_CPUTYPE;
m_CPUTYPE = 0xff;
switch (m_CPUTYPE) {
case 255:
cout << "hit 1";
case -1:
cout << "hit 2";
case CPUTYPE_INVALID:
cout << "hit 3";
break;
default:
cout << "no hit";
break;
}
What will be the outcome then? And please elaborate.
解决方案WARNING
Your code is potentially ill-formed, and if we are dealing with a platform where
unsigned char
consists of 8 bits (which is most often the case), it definitely is.
What does the standard say?
It's is stated in the standard that two case constants shall not have the same value after conversion to integral type used by the switch-condition.
6.4.2p2
Theswitch
statement[stmt.switch]
The condition shall be of intergral type, enumeration type, or class type. If of class type, the condition is contextually implicitly converted (Clause 4) to an integral or enumeration type. Integral promotions are performed. Any statement within the
switch
statement can be labeled with one or more case labels as follows:case constant-expression :
where teh constant-expression shall be a converted constant expression (5.19) of the promoted type of the switch condition. No two of the case constants in the same switch shall have the same value after conversion to the promoted type of the switch condition.
This means that if the integral type yield by the integral promotion from the type of m_CPUTYPE
, treats static_cast<int> ((BYTE)-1)
and static_cast<int> (255)
as being the same value.. the snippet is ill-formed.
So, am I safe?
Integral promotion is the method of which an integral type is promoted to another type,if that is necessary to easy implementation and logic when dealing with two integral values that are potentially of different types.
4.5
Integral promotions[conv.prom]
A prvalue of an integer type other than bool, char16_t, char32_t, or wchar_t whose integer conversion rank (4.13) is less than the rank of
int
can be converted to a prvalue of typeint
ifint
can represent all the values of the source type; otherwise, the source prvalue can be converted to a prvalue of typeunsigned int
.
It's stated in the standard that unsigned char
has less rank than int
, and with this the type of the switch condition will be int
, which further means; static_cast<int> (-1) != static_cast<int> (255)
.
But, on most platforms the maximum value of a unsigned char is 255
which means that (BYTE)-1)
will yield a unsigned char with the value of 255
. This means that 255 == CPUTYPE_INVALID
.
switch (m_CPUTYPE) {
case 255: // (A)
cout<<"hit 1";
case -1:
cout<<"hit 2";
case CPUTYPE_INVALID: // (B), same value as (A)
cout<<"hit 3";
break;
default:
cout<<"no hit";
break;
}
You have two case constants which after conversions yields the same value: your code is ill-formed.
相关文章