2011-09-11 94 views
1

我斷言宏是這樣的:這是否得到優化?

#ifdef DEBUG 
#define ASSERT(x) ((void)(!(x) && assert_handler(#x, __FILE__, __LINE__) && (exit(-1), 1))) 
#else 
#define ASSERT(x) ((void)sizeof(x)) 

我想這是更多或防彈少,但我似乎可以用它很多聲稱的這是重要的,它們的副作用函數的返回值的情況下。如果我的發佈版本中我最終編譯

ASSERT(fgets(buffer,sizeof(buffer)/sizeof(buffer[0]),file)); 

這將成爲

((void)sizeof(fgets(buffer,sizeof(buffer)/sizeof(buffer[0]),file))); 

是否有這將讓完全優化掉的機會嗎?我相當肯定它不會(我正在調用一個函數,fgets),但確保它的條件究竟是什麼?有沒有優化器可能拋出的副作用?

+12

通常,你寫斷言,以便他們沒有任何副作用,因此可以remoevd。在自己的行上執行'fgets',保存結果,然後使用'assert(result!= NULL)'。然後定義非調試'assert'來放棄'x'。或者當我們處於這種狀態時,stdlib中沒有'assert'嗎? – delnan

+0

好的,所以斷言根本不意味着與副作用一起使用。我現在感到很傻。有我自己的斷言很好,因爲它在調試器中很容易跟蹤,而不是從某個CRT彈出,我可以控制它的行爲(特定於應用程序的alert?stderr?passive?abort program?) –

+1

「聲稱帶有side效果「有時稱爲」驗證「,所以你可以這樣命名你的宏。 「assert」通常被理解爲不需要作爲程序邏輯的一部分。 –

回答

3

斷言的通常含義是被優化掉了,所以如果你堅持它不被優化掉了,爲什麼不只是做

它可能是更好地堅持那些語義和做

#else 
#define ASSERT(x) 
#endif 

#else 
#define ASSERT(x) ((void)(x)) 
#endif 

+1

爲什麼不簡單地'#define ASSERT(x)x'? –

+0

@yi_H:好的。我想這樣,你明確地丟棄了返回值,所以沒有人可以寫'if(ASSERT(x))...' –

+1

許多想法來自這個:http://cnicholson.net/2009/02/stupid -c-tr​​icks-adventures-in-assert /看起來我需要重新評估我如何使用這些宏。也許我應該使用不同版本的斷言。 –

4

它與優化無關。當您評估sizeof表達式時,操作數永遠不會被評估。例如,

char func(void) { exit(1); } 

size_t sz = sizeof(func()); 
// same as 
size_t sz = 1; 

如果您想保留副作用,不會產生編譯器警告,可以轉換爲void尼爾的G他的回答說。

+1

Sizeof不一定在編譯時進行評估。例如,'size_t func(int x){int a [x];返回sizeof(a); }'。 –

+0

對,謝謝,忘了C99。 –