但是,旧的讨论......如何使用“箭头反模式”并将以后的每个嵌套级别封装在静态内联函数中呢?该代码看起来很干净,它是最佳的(启用优化时),并且不使用goto。简而言之,分而治之。下面是一个例子:
static inline int foo_2(int bar)
{
int return_value = 0;
if ( prepare_stuff( bar ) ) {
return_value = do_the_thing( bar );
}
cleanup_3();
return return_value;
}
static inline int foo_1(int bar)
{
int return_value = 0;
if ( init_stuff( bar ) ) {
return_value = foo_2(bar);
}
cleanup_2();
return return_value;
}
int foo(int bar)
{
int return_value = 0;
if (do_something(bar)) {
return_value = foo_1(bar);
}
cleanup_1();
return return_value;
}
就空间而言,我们在堆栈中创建了三倍的变量,这并不好,但是在此简单示例中,使用-O2从堆栈中删除变量并使用寄存器时,该变量消失了。我从上面的代码块得到的gcc -S -O2 test.c
是以下内容:
.section __TEXT,__text,regular,pure_instructions
.macosx_version_min 10, 13
.globl _foo ## -- Begin function foo
.p2align 4, 0x90
_foo: ## @foo
.cfi_startproc
## %bb.0:
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset %rbp, -16
movq %rsp, %rbp
.cfi_def_cfa_register %rbp
pushq %r14
pushq %rbx
.cfi_offset %rbx, -32
.cfi_offset %r14, -24
movl %edi, %ebx
xorl %r14d, %r14d
xorl %eax, %eax
callq _do_something
testl %eax, %eax
je LBB0_6
## %bb.1:
xorl %r14d, %r14d
xorl %eax, %eax
movl %ebx, %edi
callq _init_stuff
testl %eax, %eax
je LBB0_5
## %bb.2:
xorl %r14d, %r14d
xorl %eax, %eax
movl %ebx, %edi
callq _prepare_stuff
testl %eax, %eax
je LBB0_4
## %bb.3:
xorl %eax, %eax
movl %ebx, %edi
callq _do_the_thing
movl %eax, %r14d
LBB0_4:
xorl %eax, %eax
callq _cleanup_3
LBB0_5:
xorl %eax, %eax
callq _cleanup_2
LBB0_6:
xorl %eax, %eax
callq _cleanup_1
movl %r14d, %eax
popq %rbx
popq %r14
popq %rbp
retq
.cfi_endproc
## -- End function
.subsections_via_symbols