Reputation: 591
I would like to use a (const) struct member as a selector in switch/case statement. The problem is that I get a "case expression not constant" or "illegal constant expression". Here is a brief example
#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;
}
The case VALUE_2.value_
option generates the compiler error. BTW, VALUE_2 is indeed a constant.
I'm working with ANSI C. C++ gives the same error, anyway.
Any hints?
Upvotes: 1
Views: 4932
Reputation: 332
If you make the const member static, it will satisfy the requirements for switch.
struct my_struct
{
static const int value_a = 1;
static const int value_b = 2;
void handle_value(int value)
{
switch(value)
{
case my_struct::value_a:
{
// Do something fancy
break;
}
case my_struct::value_b:
{
// Do something fancy
break;
}
default:
{
// Do something fancy
break;
}
}
}
};
Upvotes: 0
Reputation: 5543
In short, const
doesn't mean “constant expression” (the const
keyword is a little confusing IMO). Precisely,
C11 6.8.4.2 p.2 (emph. mine)
The expression of each case label shall be an integer constant expression […]
So, the question is, what an integer constant expression is; C11 addresses this in 6.6:
Description (p. 2)
A constant expression can be evaluated during translation rather than runtime, and accordingly may be used in any place that a constant may be.
The Constraints section (p. 3/4) goes on:
Constant expressions shall not contain assignment, increment, decrement, function-call, or comma operators, except when they are contained within a subexpression that is not evaluated.115)
Each constant expression shall evaluate to a constant that is in the range of representable values for its type.
And the footnote:
115) The operand of a sizeof or _Alignof operator is usually not evaluated (6.5.3.4).
Semantics (p. 5/6)
An expression that evaluates to a constant is required in several contexts. […] An integer constant expression shall have integer type and shall only have operands that are integer constants, enumeration constants, character constants,
sizeof
expressions whose results are integer constants,_Alignof
expressions, and floating constants that are the immediate operands of casts. Cast operators in an integer constant expression shall only convert arithmetic types to integer types, except as part of an operand to thesizeof
or_Alignof
operator. [emph. mine, omitted footnotes 116 and 117]
The emphasized list of allowed operands doesn't contain variables (at least not in general, sizeof VALUE_2
would be OK), no matter if they are const
-qualified or not (you mentioned C++ in your question; if you're interested, have a look at C++11's constexpr
).
And (ibid. p. 10)
An implementation may accept other forms of constant expressions.
I quoted C11; C99 is basically the same (but doesn't have the _Alignof
operator), with the same sections.
HTH
Upvotes: 1
Reputation: 4433
In C, a const
-qualified variable means "read only object in memory", but it's not considered an integer constant expression.
An integer constant expression is, roughly speaking, an expression involving only literal integer constants as operands.
In particular, a #define
-d constant which expand to an integer literal is a valid constant here.
The case
labels require integer constant expressions, and not variables. The const
qualifier is not making any difference, and this kind of objects are not allowed.
Upvotes: 2