Tiếp tục xây dựng trên Jerry's answer và những người khác
Given:
int x=1;
switch (i) {
case 1: x=6; break;
case 2: x++;
// Fall through
case 3: x+=7; break;
}
bạn có thể có một cái gì đó như sau:
int f1() {return 6;}
int f2() {return 1+f3();}
int f3() {return 8;}
Các trình biên dịch có thể sử dụng một bảng nhảy để index {f1, f2, f3}
Trình biên dịch có thể thực hiện nội tuyến khi tạo bảng có f1, f2, f3
thiết x
trực tiếp đến 6,9,8
Nhưng nếu bạn đã viết các chức năng, và cán bảng nhảy của riêng bạn, f1,f2,f3
có thể là bất cứ nơi nào, nhưng trình biên dịch sẽ biết phải đặt chúng gần với switch
tạo tốt hơn nhiều mã địa phương hơn bạn có thể.
Lưu ý rằng trong nhiều trường hợp trình biên dịch sẽ tạo ra một người bảo vệ để kiểm tra xem i
nằm trong phạm vi (hoặc để xử lý các default
) và nếu bạn chắc chắn rằng nó luôn luôn là một trong những trường hợp, bạn có thể bỏ qua mà
điều thú vị là cho dưới một số ít trường hợp, và dưới cờ biên dịch khác nhau (biên dịch phụ thuộc) các switch
sẽ không sử dụng một bảng, nhưng sẽ chỉ làm IFS, tương tự như:
if (i==1) x=f1();
else if (i==2) x=f2();
else if (i==3) x=f3();
hoặc nó có thể tối ưu hóa điều này (nơi các bài kiểm tra đơn giản là một hướng dẫn) tới:
x=(i==1) ? f1()
: (i==2) ? f2()
: (i==3) ? f3()
: x;
Lời khuyên tốt nhất là nhìn vào lắp ráp tạo ra để xem những gì các trình biên dịch đã làm cho mã của bạn trên kiến trúc của bạn, g ++ trên Linux/intel sẽ tạo ra một cái gì đó như sau, nếu có một bảng nhảy
(lưu ý tôi đã phải đi đến 5 case
báo cáo để buộc các bảng nhảy, nó được sử dụng IFS thấp hơn số case
báo cáo)
Lưu ý rằng các lỗ nhỏ sẽ nằm trong bảng nhảy để làm default
int foo(int i)
{
int x=1;
switch (i) {
case 1: x=6; break;
case 2: x++;
// Fall through
case 3: x+=7; break;
case 4: x+=2; break;
case 5: x+=9; break;
}
return x;
}
sẽ tạo mã lắp ráp sau (// ý kiến là của tôi):
cmp edi, 5 //make sure it is not over 5
ja .L2 //jump to default case
mov edi, edi
jmp [QWORD PTR .L4[0+rdi*8]] // use the jump table at label L4:
.L4:
.quad .L2 // if i=0, set x=1 (default)
.quad .L9 // f1() see below
.quad .L10 // f2() see below
.quad .L6 // f3() see below
.quad .L7 // f4() see below
.quad .L8 // f5() see below
.L10:
mov eax, 9 // x=9
ret
.L9:
mov eax, 6 // x=6
ret
.L8:
mov eax, 10 // x=10
ret
.L6:
mov eax, 8 // x=8
ret
.L7:
mov eax, 3 // x=3
ret
.L2:
mov eax, 1 // default, x was 1, noop is: x=1
ret
Thông thường, một "từ điển" giống như một thẻ bắt đầu bằng #. –