2

Is it possible to get the number of cases in a switch case in C without manually adding a counter variable which is incremented in each case?

floquet22
  • 323
  • 2
  • 15
  • 3
    You mean count the number of 'case' statements that you've written or macro-generated? I don't think you could use a counter for that - they wouldn't execute unless you went through each code path. I'm curious what you'd need this for? – Rup Feb 10 '16 at 10:05
  • 2
    I would say the short answer is "No, you can't". However, it sounds to me that your problem is better solvable with a dispatch table rather that switch statement. (At least think about it.) – Øystein Schønning-Johansen Feb 10 '16 at 10:16
  • 4
    Your question is possibly an [XY problem](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). What is it you are really trying to achieve? – kaylum Feb 10 '16 at 10:18
  • ugly fall-truh-cases without `break`? – Peter Miehle Feb 10 '16 at 10:40
  • @PeterMiehle that occurred to me too, but I was too afraid to post it:) – Martin James Feb 10 '16 at 11:13
  • This can be done easily if each case value is taken from an enumeration where all the values are contiguous, and ALL of them are used in the switch block. But in general this kind of thing isn't normally useful to know. Are you using an enum in this manner? –  Feb 10 '16 at 11:22
  • of course the counter incremented in each case was nonsense. – floquet22 Feb 10 '16 at 12:17
  • Plese **edit your question** to motivate it and explain exactly **why** you are asking that. Smells like an [XY problem](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). – Basile Starynkevitch Mar 04 '16 at 12:51

3 Answers3

7

As I commented earlier, I think you want a dispatch table rather than a switch statement. Here's a little example.

Say you got this:

int find_the_case();
void do_something();
void do_something_different();
void do_something_completly_different();
void do_default();

int main(int argc, char *argv[])
{
    int c = find_the_case();
    switch(c){
        case 0:
           do_something();
           break;
        case 1:
           do_something_different();
           break;
        case 5:
           do_something_completly_different();
           break;
        default:
           do_default();
           break;
    }
    return 0;
}

Now this ca be rewritten to this:

#define MAX_NUMBER_OF_CASES 6
int main_dispatchtable()
{
    void (*table[MAX_NUMBER_OF_CASES])(void)  = {
            [0] = do_something,
            [1] = do_something_different,
            [5] = do_something_completly_different
    };

    int c = find_the_case();
    if( table[c] )
            table[c]();
    else
            do_default();

    /* for the counting */
    int count = 0;
    for (int i = 0; i < MAX_NUMBER_OF_CASES; i++ )
            if( table[i] ) count++;

    return 0;
}

This is usually a much better way than using switch statements. Not only does it make it simpler to add more cases, but it also allows counting of cases. If you have a huge table and sparse cases you can use a hash table instead of a plain array.

EDIT: Of course there are even more advantages with the dispatch table than the switch case, as you can add and remove and change the dispatch table dynamically. That may be the greatest advantage.

  • Notice that on some processors, a dispatch table with indirect function calls can be quite slow. *computed gotos* might be faster. See [my](http://stackoverflow.com/a/35796522/841108) answer. – Basile Starynkevitch Mar 04 '16 at 13:00
6

This is horrible, but if you are under gcc you can use the COUNTER macro:

#include <stdio.h>

#define ncase (void)__COUNTER__; case

int main(void)
{
    int n = __COUNTER__ + 1;

    switch (1 + 1) {
        ncase 0: break;
        ncase 1: break;
        ncase 2: break;
    }
    n = __COUNTER__ - n;
    printf("%d cases\n", n);
    return 0;
}

Output:

3 cases
David Ranieri
  • 39,972
  • 7
  • 52
  • 94
1

(I hope you are on Linux and using a recent GCC compiler)

If you want to count the actual number of cases as seen by the compiler (think of case ranges), you need to know the compiler internal representations, and you could, if compiling with a recent GCC, customize your compiler using GCC MELT and coding our own MELT extension.

BTW, the complexity or efficiency of a switch statement is not only (or mostly) related to the number of cases (since the distribution of cases matters a big lot). See the references here.

Perhaps you might simply use the findgimple mode of GCC MELT to find switch gimple statements which are wide enough.

Maybe you want computed gotos for threaded code...

Community
  • 1
  • 1
Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547