简体   繁体   中英

Why aren't we allowed to use even global const qualified variables in switch-case?IBM support portal hints we can

Huh it's getting so muddy.The following IBM Support Portal link seems to suggest that the reason we can't use const qualified variables as real constants is because their life-time is not the same as that of the program itself.It seems to say that only about local variables as global variables have the same lifetime as the program. ( IBMLINK ).Here's what exactly it says :

An object that is declared const is guaranteed to remain constant for its lifetime, not throughout the entire execution of the program. For this reason, a const object cannot be used in constant expressions.

But in the following program,since the lifetime of the const qualified variable is the same as that of the execution of the program, why I still get the error when I use it after case in the switch-case statement,where a constant is expected?It gives the following error:

|11|error: case label does not reduce to an integer constant|

#include<stdio.h>

const int x=2;

int main(void)
{

switch(2)
{
    case 1:
    printf("Hello");
    break;
    case x:
    printf("Hola");
}

}

The reason C has strict restrictions on what can be used in a constant expression is to allow:

  1. Simple compiler implementations,
  2. Simple linker implementations, and
  3. Highly efficient code generation

For global const-qualified variables with internal linkage, allowing them in constant expressions would not be too costly. It need not impact items 2 and 3 above, just item 1. But in general (possibly external linkage), allowing them would mean:

  1. The compiler needs to leave an allowance (relocation of some sort) to resolve not just the address but the value at that address at link time. In general, this problem is as difficult as full program-at-once/link-time-optimization, which the standard does not require. In some special cases it might not need such a powerful solution.

  2. The linker must be able to handle evaluation of complex expressions based on relocations: not just address constants but values, and thereby, all expressions you can legally derive from those values.

  3. In the case of switch, the efficient implementations (jump table or binary tree of conditionals) are both ruled out if the compiler doesn't know the values of the case labels. This could be solved by moving all the work to link-time (program-at-once/LTO).

I think you're reading your own message into that quote.

An object that is declared const is guaranteed to remain constant for its lifetime, not throughout the entire execution of the program. For this reason, a const object cannot be used in constant expressions.

This is saying in the second sentence that no const objects are allowed in constant expressions, none at all.

The reason for it is given in the first sentence and, while we can envisage situations where it would be possible to use a const object that way, that in no way changes the definitive second sentence.

It's not that much different from a pre-school banning all dogs because the more aggressive ones might bite the children.


The C standard dictates this behaviour so it's not really something you should hold against IBM. Their documentation may be vague (in some readings) but they are doing the correct thing.

In (C99) 6.8.4.2 The switch statement /3 , we see:

The expression of each case label shall be an integer constant expression and no two of the case constant expressions in the same switch statement shall have the same value after conversion.

And in 6.6 Constant expressions /6 of that same standard, it defines integer constant expression thus:

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, 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 the sizeof operator.

As you can see, there's no mention of const variables there.

The problem is that the value of x is not established until run time, but case label expressions (and non-VLA array dimensions) need to be known at compile time so that the compiler can generate the appropriate code. At compile time, all that the compiler knows about x is that it is an identifier and has integer type; it does not have a value associated with it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM