什么促销类型用于switch-case表达式比较?

时间:2014-06-06 09:53:59

标签: c++ c language-lawyer

以下程序打印" unknown"用不同的编译器编译时。为什么会这样?

#include "stdio.h"

const char OPTION = (char)(unsigned char)253;

int main(int argc, char* argv[])
{
    unsigned char c = 253;
    switch (c)
    {
    case OPTION:
        printf("option\n");
        break;
    default:
        printf("unknown\n");
        break;
    }

    return 0;
}

在查看C ++标准(N3690 2013-05-05)时,我看到了switch的一个子句:

  

6.4.2 switch语句

     

2条件应为整数类型,枚举   类型或类类型。如果是类类型,则条件是上下文的   隐式转换(第4条)为整数或枚举类型。   执行整体促销。交换机内的任何声明   声明可以用一个或多个案例标签标记,如下所示:

case constant-expression :  
     

其中constant-expression应为a   转换常量表达式(5.19)的升级类型   切换条件。在同一个开关中没有两个case常量   转换为推广类型后,应具有相同的值   切换条件。

引用的转化条款:

  

4次标准转换

     

2 [注意:具有给定类型的表达式将在多个上下文中隐式转换为其他类型:
  [...]
   - 用于表达switch语句时。目的地类型是积分(6.4)   [...]
   - 后注]

变量c的类型为unsigned char,它是一个整数类型。所以不需要晋升!?

如果推广类型为unsigned char,我会期望像c == (unsigned char)OPTION这样的比较产生真实。如果推荐类型为int,我会期望像(int)c == (int)OPTION)这样的比较明显产生错误。

我的问题是:上述计划中使用的推广类型是什么? C和C ++标准中的相关条款是什么?

3 个答案:

答案 0 :(得分:6)

涉及哪些类型?

推广类型将为int,如以下部分所述:

  

4.5p1 整体促销 [conv.prom]

     
    

bool, char16_t, char32_t,wchar_t之外的整数类型的prvalue,其整数转换等级(4.13)小于int的等级如果int可以表示源类型的所有值,则可以转换为int类型的prvalue;否则,源prvalue可以转换为unsigned int类型的prvalue。

  

为什么代码在不同平台上的表现不同?

它的实现定义 char 是签名还是无符号,可以在标准的以下部分中阅读;

  

3.9.1p1 基本类型 [basic.fundamental]

     
    

实施定义char是否可以保留负值。可以明确声明字符signedunsigned

         

...

         

在任何特定实现中,普通char对象可以采用与signed charunsigned char;相同的值,其中一个是实现定义的。

  

这有什么关系?

之前引用的部分意味着对以下行的char的强制转换不必产生253的值。

const char OPTION = (char)(unsigned char)253;

如果 char 能够在 char 为8bit的平台上保留负值,253将不适合,并且很可能是初始化后OPTION的值为-3


换句话说......

整体提升后,在你的帖子中,交换机在语义上等同于下面的 if-else-statement ,因为我们有一个条件和一个默认情况。

unsigned char c = 253;

//   .---------.-------------------- integral promotion
//   v         v
if ((int)c == (int)OPTION) {
  printf ("OPTION\n");
} else {
  printf ("DEFAULT\n");
}

根据底层实施OPTION可能等于253-3;产生你描述的行为。


  

注意:这篇文章中的所有标准引文都来自最终的 C ++ 11 标准(草稿)n3337

答案 1 :(得分:1)

此处的相关部分是"执行整体促销。"

简短的版本是小于int的类型被提升为int(如果int不能表示值的全部范围,则为unsigned int。)

所以你将c提升为一个int,即253.并且你有OPTION的值为-3,提升为int,即-3。 (char的符号虽然与平台有关,但是这个程序在不同的平台上的行为可能不同.Char可以容纳的值范围也是平台相关的,尽管在2s上会发生253到-3的转换。 - 具有8位有符号字符的补充平台,这很常见。)

答案 2 :(得分:0)

正如报价中所述,您引用了“整体促销活动”。所以在这个表达式中

switch (c)

c将转换为int类型,其值为253,因为c是无符号整数对象。

在此标签中

case OPTION:

因为OPTION是有符号字符(我认为默认情况下char表现为有符号字符)然后符号位将被传播。

因此控件将传递给标签default,因为(int)(unsigned char)253不等于(int)(signed char)253。