Is underscore allowed in case labels?
Asked Answered
H

3

5

In some header file which I can not modify I have the following set of defines:

#define FLAG1                      (0x0000_0001)
#define FLAG2                      (0x0000_0002)
...

Then, in my code I use them in switch:

switch (aaa) {
    case FLAG1:
    ....

    case FLAG2:
    ....
}

As a result, Coverity reports on 2 defects per each case label:

RW.EXP_RPAREN: 
Event exp_rparen: expected a ")"

RW.CASE_LABEL_CONFLICT:
Event case_label_conflict: case label value has already appeared in 
this switch at line XX

What is wrong with these case labels? Does it violate C standards?

Hurleigh answered 10/2, 2011 at 13:45 Comment(7)
It shouldn't. case 4*(1+2): should be valid as well.Autogamy
What is the underscore in 0x0000_0001? That's not valid C...Lagomorph
If you take out the underscores in the hex constants it should be fine.Contrast
@kotlinski Actually, this underscore is accepted by compiler without any errors/warnings or other negative consequences...Hurleigh
If you can't get the header fixed, you are going to have to redefine the flag values yourself. You may as well use an enum. You might write (with slashes for newlines): #undef FLAG1 / #undef FLAG2 / enum { FLAG1 = 0x0001, FLAG2 = 0x0002 };. That undoes the damage from the erroneous header and gives you better debugging (because enum symbols are conveyed to the debugger, but preprocessor symbols usually are not).Arrowworm
If the underscore is accepted, you have a broken compiler - according to the C standard. Looking at it charitably, you have a compiler with a non-standard extension; don't try it with most compilers. And your syntax error becomes inexplicable. The C preprocessor won't object to the underscore; the C compiler should. Which compiler are you using?Arrowworm
@Jonathan Leffler. This is our preparatory compiler and now I have an idea to file a CR regarding this case. Thank you!Hurleigh
S
3

Yeah, it's the underscore that's causing problems. FWIW, here are the relevant sections from the C language standard (draft n1256):

  • § 6.4.4.1 Integer Constants: defines the structure for integer constants and shows that _ is not a valid character for an integer constant;
  • § 6.6 Constant Expressions: defines the restrictions on constant expressions;
  • § 6.8.4.2 The switch statement: defines the restrictions on case labels in a switch statement.
Sheridansherie answered 10/2, 2011 at 15:16 Comment(0)
R
5

Yes, you are allowed to have parentheses. What you aren't allowed to have is a number like 0x0000_0001.

That's not a valid hex number, you'll probably have to remove the _ character.

Revetment answered 10/2, 2011 at 13:52 Comment(0)
S
3

Yeah, it's the underscore that's causing problems. FWIW, here are the relevant sections from the C language standard (draft n1256):

  • § 6.4.4.1 Integer Constants: defines the structure for integer constants and shows that _ is not a valid character for an integer constant;
  • § 6.6 Constant Expressions: defines the restrictions on constant expressions;
  • § 6.8.4.2 The switch statement: defines the restrictions on case labels in a switch statement.
Sheridansherie answered 10/2, 2011 at 15:16 Comment(0)
A
2

It think it expects the ) when it finds the _ which isn't valid in hexadecimal notation.

The compiler should actually complain like this:

error: invalid suffix "_0001" on integer constant

case labels may well contain parentheses:

switch(number) {
    // no way to determine operator 
    // precedence without parens here
    case 2*(1+2):
}
Autogamy answered 10/2, 2011 at 13:51 Comment(4)
That isn't a suffix (according to the 'maximal munch' rule); it is an identifier starting with _ that is adjacent to the hex constant - and you can't write a number followed by an identifier without an intervening operator.Arrowworm
Actually, this underscore is accepted by compiler without any errors/warnings or other negative consequences...Hurleigh
@Jonathan @Pmod Not my gcc, don't. I gave it 0xdead_beef to "munch" and it complained with the exact same message I posted in the answer... Lookie hereAutogamy
The only reason for that is because it recognizes sometimes that the underscore could be embedded in a constant. Otherwise, the compiler will tokenize '(0x0000_0001)' into (, 0x000, _0001, ), which is a pair of brackets around a valid number and a valid identifier. I can't find an option that allows it; I suspct it means there is some other compiler in the world that does allow it. I have verified that I get the message you show, Linus.Arrowworm

© 2022 - 2024 — McMap. All rights reserved.