5

I know that this code does not work as "expected". Just looking quickly at this code, we think the return value should be 1, but in the execution it returns returns 3.

// incorrect
variable = 1;
switch (variable)
{
  case 1, 2:
    return 1;
  case 3, 4:
    return 2;
  default:
    return 3;
}

and there are some correct options to do this:

// correct 1
variable = 1;
switch (variable)
{
  case 1: case 2:
    return 1;
  case 3: case 4:
    return 2;
  default:
    return 3;
}

or

// correct 2
switch (variable)
{
  case 1:
  case 2:
    return 1;
  case 3:
  case 4:
    return 2;
  default:
    return 3;
}

This is partially answered in Multiple Cases in Switch:

I would like to know why the incorrect form does compile without error or even warnings (at least in the Borland C++ compiler).

What does the compiler understand in that code?

Community
  • 1
  • 1
Juliano
  • 821
  • 6
  • 21
  • 3
    You might want to check [How does the comma operator work?](http://stackoverflow.com/questions/54142/how-does-the-comma-operator-work) – Bo Persson Nov 13 '15 at 13:43

6 Answers6

8

Just looking quickly at this code, we think the return value should be 1,

I'd say that an experienced C++ developer would immediately notice that something is wrong and quickly conclude that some other programmer accidentally tried to use the comma operator: ,

but in the execution it returns returns 3.

No, the code must not compile, because the case expression is not constant

And as a matter of fact, it does not compile in any halfway modern compiler. For example, MSVC 2013 says:

stackoverflow.cpp(8) : error C2051: case expression not constant
stackoverflow.cpp(10) : error C2051: case expression not constant

An expression like 1, 2 is an application of the comma operator, and the comma operator implies that the expression is not a compile-time constant.

At least until C++11 came along and relaxed the rules to the effect that adding parentheses, i.e. case (1, 2):, would be allowed to compile. It just would not do what you seem to expect.

This is partially answered in Multiple Cases in Switch:

How so? That other question and the answers are almost exclusively about C#, not about C++.

I would like to know why the incorrect form does compile without error or event warnings (at least in the Borland C++ compiler).

Because the compiler is too old. Better get a new one.

Community
  • 1
  • 1
Christian Hackl
  • 27,051
  • 3
  • 32
  • 62
3

My guess is that in the first case the compiler evaluates the comma operators to result in the code being executed as follows:

switch(variable)
{
  case 2:
    return 1;
  case 4:
    return 2;
  default:
    return 3;
}

From above, it can be seen why the value 3 is returned for input 1. I suggest you read up about the comma operator. There are some excellent threads on SO related to it.

therainmaker
  • 4,253
  • 1
  • 22
  • 41
  • @MadPhysicist : I appreciate the gesture. Polite people on public forums is an increasing rarity. I return the feeling though, as you deserve an upvote as much as I do. :) – therainmaker Nov 13 '15 at 13:50
  • Why the down vote people? – therainmaker Nov 13 '15 at 14:04
  • @therainmaker: I did not downvote, but to be honest I can understand why one would downvote it. Guessing is not a good idea in an answer, and in this case your guess is also wrong, because the code does not even compile with a conforming compiler. – Christian Hackl Nov 13 '15 at 14:06
  • 1
    @ChristianHackl : By 'guess' I mean't what I can make out by looking at the code, but am not verifying it by running on an IDE. I guess it has different connotations for everyone. Thanks for the comment though. and I just saw you're from TU Graz. One of my good Austrian friend studies there. High five :) – therainmaker Nov 13 '15 at 14:10
3

a, b is a valid expression in both C and C++. It means "Evaluate a, discard it, evaluate b". The value of the expression is b. So your original switch has the following meaning:

variable = 1;
switch(variable)
{
  case 2:
    return 1;
  case 4:
    return 2;
  default:
    return 3;
}

For more on the comma operator, you can read the Wikipedia article.

Mad Physicist
  • 107,652
  • 25
  • 181
  • 264
3

An expression of the form a, b has a value b. That's how the comma operator works.

Ostensibly then, case 1, 2: is equivalent to case 2:, and so on.

However, a case label must be a constant integral expression , and 1, 2 is not a constant expression since it contains the comma operator (the C++ grammar dictates that a constant expression cannot contain the comma operator). Therefore your compiler should issue an error.

You'll often see case 1: case 2: which, due to the follow-through behaviour of the switch, will allow the statement following that line to be run for both the 1 and 2 cases.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
1

Do some experiment.

#include <stdio.h>

int test(int variable) {
  switch (variable)
  {
    case 1, 2:
      return 1;
    case 3, 4:
      return 2;
    default:
      return 3;
  }
}

int main(void) {
  int i;

  for (i = 1; i <= 5; i++)
  {
    printf("%d -> %d\n", i, test(i));
  }
  return 0;
}

Compiled with Borland C++ 5.5.1 for Win32, the output was

1 -> 3
2 -> 1
3 -> 3
4 -> 2
5 -> 3

It shows that the 1, 2 is interpreted as 2 and 3, 4 is interpreted as 4.

MikeCAT
  • 73,922
  • 11
  • 45
  • 70
0

In C or C++, comma expressions have following rules:

  1. Operate from left to right.
  2. Value of comma expression is the value of the last expression.

So the code case 1,2: equals to case 2: due to the fact that comma expression has the value of 2.

Qin Tianyi
  • 71
  • 1