在 C 中执行案例 a ... z 的便携式方法
Portable way to do case a ... z in C
我正在使用以下 GCC 扩展来简化一个大的 switch 语句:
case 'a' ... 'z':
...
执行此操作的 proper/portable 方法是什么 -- 即,遍历一个大开关中的所有字母 -- 或者为此不应该使用开关。
如果您希望所有大小写 'a' 到 'z'(所有小写字母)都具有相同的效果,那么您可以执行以下操作
#include <ctype.h>
if(isalpha(c) && islower(c))
{
//..Do Whatever...
}
请记住,当 none 的情况为真时,default
可用于执行任务:
switch (x)
{
case 1:
case 2:
printf("%d\n", x);
break;
default:
if (islower(x))
{
puts("alpha");
}
break;
}
另一种使用臭名昭著的方法 goto
:
if (islower(x))
goto alpha;
switch (x)
{
alpha:
printf("alpha\n");
break;
case 1:
case 2:
printf("%d\n", x);
break;
}
我会'go through all the letters in a big switch'.
仅仅是因为编译器(gcc 或 clang)将再次优化此 'away'。
如果您比较以下代码:
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;
}
}
生成汇编代码 (gcc)
(注意:97== 'a' 和 122 == 'z'),它基本上将您的代码更改为
类似于 if(c>'z')
和 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
因此生成的汇编代码针对速度和大小进行了优化。
我正在使用以下 GCC 扩展来简化一个大的 switch 语句:
case 'a' ... 'z':
...
执行此操作的 proper/portable 方法是什么 -- 即,遍历一个大开关中的所有字母 -- 或者为此不应该使用开关。
如果您希望所有大小写 'a' 到 'z'(所有小写字母)都具有相同的效果,那么您可以执行以下操作
#include <ctype.h>
if(isalpha(c) && islower(c))
{
//..Do Whatever...
}
请记住,当 none 的情况为真时,default
可用于执行任务:
switch (x)
{
case 1:
case 2:
printf("%d\n", x);
break;
default:
if (islower(x))
{
puts("alpha");
}
break;
}
另一种使用臭名昭著的方法 goto
:
if (islower(x))
goto alpha;
switch (x)
{
alpha:
printf("alpha\n");
break;
case 1:
case 2:
printf("%d\n", x);
break;
}
我会'go through all the letters in a big switch'.
仅仅是因为编译器(gcc 或 clang)将再次优化此 'away'。
如果您比较以下代码:
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;
}
}
生成汇编代码 (gcc)
(注意:97== 'a' 和 122 == 'z'),它基本上将您的代码更改为
类似于 if(c>'z')
和 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
因此生成的汇编代码针对速度和大小进行了优化。