我正在学习 switch 语句在 C 中如何工作,所以我决定查看编译后的代码。据我了解,C 使用跳转表来实现 switch 语句。但是,我在汇编代码中没有看到任何标签或跳转指令。
我用的是苹果芯片,所以是ARM组装的。请看一下并告诉我您的想法。谢谢:)
C代码:
int main (int argc, char *argv[]) {
int one;
int two;
int three;
int four;
switch (1) {
case 1:
one = 1;
break;
case 2:
two = 2;
break;
case 3:
three = 3;
break;
default:
four = 4;
break;
}
return 0;
}
ARM代码:
.section __TEXT,__text,regular,pure_instructions
.build_version macos, 14, 0 sdk_version 14, 4
.globl _main ; -- Begin function main
.p2align 2
_main: ; @main
.cfi_startproc
; %bb.0:
sub sp, sp, #32
.cfi_def_cfa_offset 32
mov x8, x0
mov w0, #0
str wzr, [sp, #28]
str w8, [sp, #24]
str x1, [sp, #16]
mov w8, #1
str w8, [sp, #12]
add sp, sp, #32
ret
.cfi_endproc
; -- End function
.subsections_via_symbols
C 编译器可以根据所谓的 as-if 规则 自由地转换程序。这意味着通过充分的优化,OP 程序可以减少到仅返回 0。
为了避免此类优化,常见的方法是设置变量
volatile
。这样就可以看到OP代码的完整翻译了:
sub sp, sp, #24
movs r3, #1
str r3, [sp, #20]
ldr r3, [sp, #20]
cmp r3, #2
it eq
streq r3, [sp, #8]
beq .L5
cmp r3, #3
it eq
streq r3, [sp, #12]
beq .L5
cmp r3, #1
itee eq
streq r3, [sp, #4]
movne r3, #4
strne r3, [sp, #16]
.L5:
movs r0, #0
add sp, sp, #24
bx lr
因此,在这种情况下,编译器仍然会进行一系列比较,大概是因为这比查找表更有效。可能,如果有更多情况,它将使用查找表,但无论如何,现代编译器将竭尽全力制作最高效的代码,以便我们可以专注于编写最可读的代码。