Теоретически для полного переключения компилятор сгенерирует таблицу переходов, то есть массив указателей на метки для прямой индексации (при условии, что значение соответствует диапазону).
Для менее полной версии, компилятор должен балансировать таблицу переходов и операторы ветвления. Вероятно, это также будет зависеть от настроек: увеличите ли вы скорость с помощью -O3
или уменьшите размер с помощью -Oz
, что определенно повлияет на некоторые крайние случаи.
Наконец, коммутатор имеет только один регистр, вероятно, вместо этого он будет представлен как ветвь.
Наличие break
или прорыв не сильно влияет на вещи. Сборка определяется в терминах меток, и как break
, так и спад представлены естественным образом, поэтому это не должно влиять на то, используются ли ветви или таблицы переходов.
Демонстрация (с помощью веб-сайта Try out LLVM)
enum Enum {
Zero,
One,
Two,
Three,
Four,
Five,
Six,
Seven,
Eight,
Nine
};
char const* full(enum Enum e) {
switch(e) {
case Zero: return "Zero";
case One: return "One";
case Two: return "Two";
case Three: return "Three";
case Four: return "Four";
case Five: return "Five";
case Six: return "Six";
case Seven: return "Seven";
case Eight: return "Eight";
case Nine: return "Nine";
}
return "Uh ?";
}
char const* sparse(enum Enum e) {
switch(e) {
default: return "Not handled";
case Zero: return "Zero";
case One: return "One";
case Two: return "Two";
case Seven: return "Seven";
case Eight: return "Eight";
case Nine: return "Nine";
}
}
char const* null(enum Enum e) {
switch(e) {
default: return "Not Zero";
case Zero: return "Zero";
}
}
Функция full
скомпилирована в:
.text
.globl full
.align 16, 0x90
.type full,@function
full: # @full
.Ltmp0:
.cfi_startproc
# BB#0:
cmpl $9, %edi
ja .LBB0_11
# BB#1:
movl %edi, %ecx
movl $.L.str, %eax
jmpq *.LJTI0_0(,%rcx,8)
.LBB0_2:
movl $.L.str1, %eax
ret
.LBB0_3:
movl $.L.str2, %eax
ret
.LBB0_4:
movl $.L.str3, %eax
ret
.LBB0_5:
movl $.L.str4, %eax
ret
.LBB0_6:
movl $.L.str5, %eax
ret
.LBB0_7:
movl $.L.str6, %eax
ret
.LBB0_8:
movl $.L.str7, %eax
ret
.LBB0_9:
movl $.L.str8, %eax
ret
.LBB0_10:
movl $.L.str9, %eax
ret
.LBB0_11:
movl $.L.str10, %eax
.LBB0_12:
ret
.Ltmp1:
.size full, .Ltmp1-full
.Ltmp2:
.cfi_endproc
.Leh_func_end0:
.section .rodata,"a",@progbits
.align 8
.LJTI0_0:
.quad .LBB0_12
.quad .LBB0_2
.quad .LBB0_3
.quad .LBB0_4
.quad .LBB0_5
.quad .LBB0_6
.quad .LBB0_7
.quad .LBB0_8
.quad .LBB0_9
.quad .LBB0_10
И функция sparse
до:
.text
.globl sparse
.align 16, 0x90
.type sparse,@function
sparse: # @sparse
.Ltmp3:
.cfi_startproc
# BB#0:
movl $.L.str11, %eax
cmpl $9, %edi
ja .LBB1_8
# BB#1:
movl %edi, %ecx
jmpq *.LJTI1_0(,%rcx,8)
.LBB1_2:
movl $.L.str, %eax
ret
.LBB1_3:
movl $.L.str1, %eax
ret
.LBB1_4:
movl $.L.str2, %eax
ret
.LBB1_5:
movl $.L.str7, %eax
ret
.LBB1_6:
movl $.L.str8, %eax
ret
.LBB1_7:
movl $.L.str9, %eax
.LBB1_8:
ret
.Ltmp4:
.size sparse, .Ltmp4-sparse
.Ltmp5:
.cfi_endproc
.Leh_func_end1:
.section .rodata,"a",@progbits
.align 8
.LJTI1_0:
.quad .LBB1_2
.quad .LBB1_3
.quad .LBB1_4
.quad .LBB1_8
.quad .LBB1_8
.quad .LBB1_8
.quad .LBB1_8
.quad .LBB1_5
.quad .LBB1_6
.quad .LBB1_7
И, наконец, функция null
:
.text
.globl null
.align 16, 0x90
.type null,@function
null: # @null
.Ltmp0:
.cfi_startproc
# BB#0:
movl $.L.str1, %ecx
testl %edi, %edi
movl $.L.str, %eax
cmoveq %rcx, %rax
ret
.Ltmp1:
.size null, .Ltmp1-null
.Ltmp2:
.cfi_endproc
.Leh_func_end0: