[英]is `warning C4127` (conditional expression is constant) ever helpful?
回答這篇文章時,我建議對多行宏使用do {...} while(0)
。
在MSVC上,我發現此代碼拋出:
warning C4127: conditional expression is constant
為了使代碼無警告,我需要選擇以下丑陋的替代方案之一:
選項1
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4127)
#endif
code_using_macro_that_generates_C4217;
#ifdef _MSC_VER
#pragma warning(pop)
#endif
選項2
將我的宏定義為:
#define MULTI_LINE_MACRO do { ... } while(0,0)
要么
#define MULTI_LINE_MACRO do { ... } while((void)0,0)
一些程序員也稱為“貓頭鷹”,因為(0,0)
看起來像貓頭鷹。
選項3
定義一個新的宏WHILE_0,它不會生成警告並使用它而不是while(0)
問題
我相信所有選擇都或多或少都是可怕的。 為什么MSVC會為看似正確的代碼生成此警告,並激勵我在代碼中添加一些丑陋以保持代碼警告免費?
我相信條件中的常量表達式是完全有效的,特別是在基於編譯器優化代碼的能力的構造中。
此外,我沒有得到warning C4127
的代碼warning C4127
:
void foo(unsigned bar)
{
while (bar >= 0)
;
}
我的問題是:不是warning C4127: conditional expression is constant
完全沒用,它不會激發丑陋的代碼嗎? 這個警告是否有助於編寫更好的代碼?
我不認為它有用。 相反,有更多的誤報而不僅僅是do .. while(0)
成語。 想想像這樣的結構
if(sizeof(long) == 8) { /* ... */ }
if(SOME_CONSTANT_MACRO) { /* ... */ }
前者不能被#if
指令替換,后者可以,但是一些編碼風格指南更喜歡if
版本,因為仍然對死代碼進行語法檢查(在其他平台或其他編譯時配置中沒有死)有些人發現閱讀起來更好。
警告(除了標准所要求的警告之外,其中大多數應被視為錯誤)通常是針對有效的代碼發出的,但可能會執行除預期之外的其他操作。 if(0)
或類似的東西看起來很傻,但看起來不像“語法檢查這個否則死代碼”的意圖。 它可能會困擾讀者,但它是明確的,我不知道這是如何偶然發生的。
從目前給出的示例(我沒有自己的MSVC進行測試),似乎警告是針對C語言意義上的常量表達式(也就是說,不是可以是常量折疊但是語法上的東西不是一個常量表達式),所以它不是為if(array)
或者if(function)
發出的(例如gcc -Wall
會發出警告,因為它可能是一個函數調用)。
while(0,0)
更糟糕,在我看來,它會觸發一個警告,用gcc -Wall
表示逗號操作符的左側沒有副作用,我可以想象這個警告偶爾會有用(通常是容易避免)。 while((void)0,0)
此警告消失。
我建議關閉警告。
該條件表達式是恆定一定的警告可以是有用的。 在許多情況下,它可能指向代碼中的邏輯錯誤。
例如,如果您寫的內容如下:
if (x != NULL) { /* ... */ }
其中x
是數組對象,表達式有效,但表達式x
衰減到指向數組初始元素的指針,該元素不能是空指針。 我不知道是否會產生相同的錯誤,但它是同類錯誤的一個例子。
當然,它並不總是有用的。 在你的情況下,
do { /* ... */ } while (0)
idiom是編寫宏定義的最佳方式,該宏定義旨在用於需要語句的上下文中。 在另一個上下文中使用while (0)
可能是一個邏輯錯誤[*]。
不幸的是,你的編譯器並不認為它是一個常見的習慣用法。 產生良好的警告是棘手的; 編譯器必須超越語言規則並推斷程序員的意圖。
在這種情況下,使用一些特定於編譯器的方法來抑制警告(只要它不破壞其他編譯器的代碼)可能是最好的方法。 在所有情況下使用命令行選項來抑制警告將是過度的; 你可能會錯過代碼中其他地方的有效警告。
顯然寫入while (0,0)
而不是while (0)
可以避免警告。 如果您這樣做,您應該添加一個注釋,清楚地表明它是您的特定編譯器的解決方法。 編譯器不應該警告while (0,0)
或任何其他等效代碼沒有特殊原因。
[*]如果你想能夠使用break
來跳出它,那么寫一個do { /* ... */ } while (0)
語句是有意義的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.