Portable way to do case a ... z in C

Viewed 103

I'm using the following GCC extension to simplifying a big switch statement:

case 'a' ... 'z':
   ...

What's the proper/portable way to do this -- i.e., go through all the letters in a big switch -- or for this should a switch not be used.

3 Answers

Remember that default can be used for performing a task when none of the cases is true:

switch (x)
{
    case 1:
    case 2:
        printf("%d\n", x);
        break;
    default:
        if (islower(x))
        {
            puts("alpha");
        }
        break;
}

Another way using the infamous goto:

if (islower(x))
    goto alpha;

switch (x)
{
    alpha:
        printf("alpha\n");
        break;
    case 1:
    case 2:
        printf("%d\n", x);
        break;
}

I would 'go through all the letters in a big switch'.
Simply because the compiler (gcc or clang) will optimize this 'away' again. If you compare following code:

void func0(int x)
{
    switch( x )
    {
    case 'a':case 'b':case 'c':case 'd':case 'e':
    case 'f':case 'g':case 'h':case 'i':case 'j':
    case 'k':case 'l':case 'm':case 'n':case 'o':
    case 'p':case 'q':case 'r':case 's':case 't':
    case 'u':case 'v':case 'w':case 'x':case 'y':
    case 'z':
        func1(x);
        break;
    case 1001:
        func2(x);
        break;
    default:
        func3(x);
        break;
    }
}

with the assembly code generated (gcc) (note: 97== 'a' and 122 == 'z'), it basically changed your code to something similar to if(c>'z') and if(c<'a') :

func0:
        push    rbp
        .seh_pushreg    rbp
        mov     rbp, rsp
        .seh_setframe   rbp, 0
        sub     rsp, 32
        .seh_stackalloc 32
        .seh_endprologue
        mov     DWORD PTR 16[rbp], ecx
        cmp     DWORD PTR 16[rbp], 122
        jg      .L2
        cmp     DWORD PTR 16[rbp], 97
        jge     .L3
        jmp     .L4
.L2:
        cmp     DWORD PTR 16[rbp], 1001
        je      .L5
        jmp     .L4
.L3:
        mov     ecx, DWORD PTR 16[rbp]
        call    func1
        jmp     .L6
.L5:
        mov     ecx, DWORD PTR 16[rbp]
        call    func2
        jmp     .L6
.L4:
        mov     ecx, DWORD PTR 16[rbp]
        call    func3
        nop
.L6:
        nop
        add     rsp, 32
        pop     rbp
        ret

so the resulting assembly code is both optimized for speed and size.

If you want all cases 'a' to 'z' (all lower case alphabets) to have the same effect then you can do the following

#include <ctype.h>

if(isalpha(c) && islower(c))
{
        //..Do Whatever... 
}
Related