Posted on June 19th, 2010 at 22:35 by fr3@K
你一定看過這樣的 code:
-
int do_something(size_t n)
-
{
-
int result = ERROR;
-
char* buf;
-
-
if(n)
-
{
-
buf = malloc(n);
-
if(buf != 0)
-
{
-
if(do_foo(buf, n) == OKAY)
-
{
-
if(do_bar(buf, n) == OKAY)
-
result = OKAY;
-
}
-
free(buf);
-
}
-
}
-
-
return result;
-
}
可讀性差的巢狀 if block, 只為了堅持由一處 return.
想必也看過這樣的 code:
-
int do_something(size_t n)
-
{
-
char* buf;
-
-
if(n == 0)
-
return ERROR;
-
-
buf = malloc(n);
-
if(buf == 0)
-
return ERROR;
-
-
if(do_foo(buf, n) != OKAY)
-
{
-
free(buf);
-
return ERROR;
-
}
-
-
if(do_bar(buf, n) != OKAY)
-
{
-
free(buf);
-
return ERROR;
-
}
-
-
return OKAY;
-
}
由多處 return 雖避掉了巢狀 if block, 但需要在多個地方 cleanup 之前所請求的資源.
當然還有這樣的 code:
-
int do_something(size_t n)
-
{
-
int result = ERROR;
-
char* buf = 0;
-
-
if(n == 0)
-
goto CLEANUP;
-
-
buf = malloc(n);
-
if(buf == 0)
-
goto CLEANUP;
-
-
if(do_foo(buf, n) != OKAY)
-
goto CLEANUP;
-
-
if(do_bar(buf, n) != OKAY)
-
goto CLEANUP;
-
-
result = OKAY;
-
-
CLEANUP:
-
// free()ing a NULL ptr is a no-op.
-
free(buf);
-
-
return result;
-
}
不管老師以前是如何叮嚀不要用 goto, 為了閃掉那噁心的巢狀 if block 以及重複的 code, 只好還是用了 goto.
其實還有另一種選擇, 不用重複寫釋放資源的 code, 也不需要用到 goto:
-
static int do_something_helper(char* buf, n)
-
{
-
if(do_foo(buf, n) != OKAY)
-
return ERROR;
-
-
if(do_bar(buf, n) != OKAY)
-
return ERROR;
-
-
return OKAY;
-
}
-
-
int do_something(size_t n)
-
{
-
int result;
-
char* buf;
-
-
if(n == 0)
-
return ERROR;
-
-
buf = malloc(n);
-
if(buf == 0)
-
return ERROR;
-
-
result = do_something_helper(buf, n);
-
-
free(buf);
-
return result;
-
}
一旦把 resource management 跟 logic 的部份拆開, code 就好看多了.
- 獻給一位因為沒有充足理由的規定, 卻在工作中被迫得寫 pure C 的可憐同事.
後記: 這應該是目前我寫的唯一一篇 pure C 的文字. 擔心它太寂寞, 還是把它打上了 C++ 的 tag.
![]() |
|
| Previous Post « 華碩品質, 以卵擊石 « |
Next Post » Did You Know, “new (nothrow) T” Throws? » |








原來是只能用
C++C (ed: must have been a typo of av – fr3@K),我看到一半還在想怎麼沒 smart pointer. 不過話說這種利用增加抽像性來解決問題的手法還真是到處都管用啊.Comment by av — June 20, 2010 @ 0:17