しかし、古い議論.... "矢印アンチパターン"を使用して、後ですべてのネストされたレベルを静的インライン関数にカプセル化するのはどうでしょうか。コードはきれいに見え、最適化され(最適化が有効な場合)、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;
}
スペースに関しては、スタックに3倍の変数を作成していますが、これは適切ではありませんが、この単純な例で変数をスタックから削除し、レジスタを使用して-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