Ranges in C Switch Statements

Whenever possible I will try and use a switch statement instead of a set of if/else blocks. I do this for a few reasons:

  1. A switch construct is more easily translated into a jump (or branch) table. This can make switch statements much more efficient than if-else when the case labels are close together. The idea is to place a bunch of jump instructions sequentially in memory and then add the value to the program counter. This replaces a sequence of comparison instructions with an add operation.
  2. I find this provides cleaner in code, this is beneficial in the long run for legacy code and general upkeep.

One drawback of switch statements…at least I used to think was the ability to specify a range of values within each case statement. For example in an if statement you can do something like this:

if(x > 3 && x < 8)

Is it possible to do so with a switch statement? It turns out if you are using GNU C then there is an extension that provides the ability to specify a range in your switch statements. An excerpt from the GCC help pages:

GNU C provides several language features not found in ISO standard C. (The -pedantic option directs GCC to print a warning message if any of these features is used.) To test for the availability of these features in conditional compilation, check for a predefined macro __GNUC__, which is always defined under GCC.

Using the ellipsis in a switch statement

To utilize a range within a case of your switch statement you can use ellipsis or “…”. This informs the compiler to check the variable against two boundaries, a minimum and maximum. I thought I better test this extension with a small program before I actually use it. This program will read in one integer value using scanf then this value is sent to the switch statement which outputs a basic string identifying where the case has been matched.

#include <stdio.h>
 
int main() {
    int x;
    scanf("%d", &x);
 
    switch (x) {
       case 1 ... 100:
           printf("1 <= %d <= 100\n", x);
           break;
       case 101 ... 200:
           printf("101 <= %d <= 200\n", x);
           break;
       default:
            break;
    }
    return 0;    
}

The corresponding program output:

$ ./main
3
1 <= 3 <= 100
 
$ ./main
121
101 <= 121 <= 200

This little test program verifies that basic values will match their case equivalent. I would suggest compiling with -pedantic to ensure your compiler supports this extension before assuming it actually works. Pretty great nonetheless.