【问题标题】:Use const struct member in switch/case statement在 switch/case 语句中使用 const struct 成员
【发布时间】:2014-07-18 10:29:15
【问题描述】:

我想在 switch/case 语句中使用 (const) 结构成员作为选择器。问题是我得到一个“case expression not constant”或“illegal constant expression”。这是一个简单的例子

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

typedef struct _myStruct
{
    unsigned int value_;
    unsigned int index_;
} myStruct;

#define VALUE_0 0
const unsigned int VALUE_1 = 1;
const myStruct VALUE_2 = {2, 0};

int main()
{
  srand((unsigned int)time(0));

  switch(rand()%4)
  {
    case VALUE_0:
      printf("Value is 0\n");
      break;
    case VALUE_1:
      printf("Value is 1\n");
      break;
    case VALUE_2.value_:
      printf("Value is 2\n");
      break;
    case 3:
      printf("Value is 3\n");
      break;
  }

  return 0;
}

case VALUE_2.value_ 选项会生成编译器错误。顺便说一句,VALUE_2 确实是一个常数。

我正在使用 ANSI C。无论如何,C++ 给出了同样的错误。

有什么提示吗?

【问题讨论】:

  • 您的案例标签不会减少到integer constant
  • 如果将 const myStruct VALUE_2 更改为 constexpr myStruct VALUE_2(在 C++11 中)以具有编译时间常数,它会编译。 const 并不意味着它在编译时是已知的。
  • 可能重复:stackoverflow.com/questions/14069737/…switch 语句中用作标签的两个问题中都有const int
  • 因为它不是一个常数。关键字const 使变量“不可写”,但不是常量。
  • @Jarod42 虽然这不是 C++11

标签: c struct switch-statement


【解决方案1】:

C中,const-qualified 变量表示“内存中的只读对象”,但它不被视为整数常量表达式

整数常量表达式,粗略地说,是一个只包含文字整数常量作为操作数的表达式。

特别是,#define-d 常量扩展为整数文字在这里是一个有效的常量

case 标签需要整数常量表达式,而不是变量。 const 限定符没有任何区别,并且不允许此类对象。

【讨论】:

  • 感谢您的回答。但是从编译器的角度来看,VALUE_1VALUE_2 之间有什么区别?它们都是只读对象,而不是预处理器常量(阅读#define)。
  • 我认为这取决于编译器,或者编译器选项。我已经在严格的标准 C99 规则下使用 GCC 4.7 编译了您的代码,并且在 VALUE1 上引发了一条错误消息,因为它不是 整数常量表达式。它不是可移植的代码。
【解决方案2】:

简而言之,const 并不意味着“常量表达式”(const 关键字在 IMO 中有点令人困惑)。没错,

C11 6.8.4.2 p.2 (emph. mine)

每个case标签的表达式应该是一个整数常量表达式 […]

所以,问题是,整数常量表达式是什么; C11 在 6.6 中解决了这个问题:

说明(第 2 页)

常量表达式可以在翻译期间而不是运行时进行计算,因此可以在常量可能存在的任何地方使用。

约束部分(第 3/4 页)继续:

常量表达式不应包含赋值、递增、递减、函数调用或逗号运算符,除非它们包含在未计算的子表达式中。115)

每个常量表达式的计算结果都应在其类型的可表示值范围内。

还有脚注:

115) sizeof 或 _Alignof 运算符的操作数通常不求值 (6.5.3.4)。

语义(第 5/6 页)

在多个上下文中都需要计算结果为常量的表达式。 […] 整数常量表达式应具有整数类型,并且只能具有整数常量、枚举常量、字符常量、sizeof 其结果为整数常量的表达式、_Alignof 表达式和浮点常量的操作数类型转换的直接操作数。整数常量表达式中的强制转换运算符只能将算术类型转换为整数类型,除非作为 sizeof_Alignof 运算符的操作数的一部分。 [嗯。我的,省略脚注 116 和 117]

强调的允许操作数列表不包含变量(至少一般情况下,sizeof VALUE_2 可以),无论它们是否是const-qualified(您在问题中提到了 C++;如果你有兴趣,看看C++11的constexpr)。

并且(同上,第 10 页)

一个实现可以接受其他形式的常量表达式。

我引用了 C11; C99 基本相同(但没有_Alignof 运算符),具有相同的部分。

HTH

【讨论】:

  • 感谢您的详细回答。我会再仔细阅读几遍,以更好地确定我脑海中的概念。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-07-09
  • 2021-02-19
  • 2016-06-27
  • 2013-09-24
  • 1970-01-01
  • 1970-01-01
  • 2014-08-05
相关资源
最近更新 更多