2011-06-06 68 views
8

假設我有類似下面的功能:如何使特定的「無符號無符號比較零」警告消失?

#define LOWER_BOUND 0 
#define UPPER_BOUND 42 

int is_value_in_range(some_typedef val) 
{ 
    return ((LOWER_BOUND <= val) && (val <= UPPER_BOUND)); 
} 

假設我已經配置了適當的警告,如果some_typedef原來是一個無符號的類型,我會得到一個警告,有一個無符號類型的無意義的比較與0.當然這是真的,它是有道理的。

但是,可以說,我要針對零檢查是在一個或多個可能的原因,如代碼:

  • 雖然界限總是會編譯時間常數,它們可能會改變(並且宏可能不會「活」到非常接近該函數)。例如,可以通過將選項傳遞給編譯器來設置邊界。
  • 我可能希望防止將typedef稍後更改爲signed類型,因爲typedef的每次使用可能在更改時都沒有仔細檢查。

是否有一個體面,合理的便攜式的方式來沉默警告,而不是完全關閉它?

某些依賴於'STATIC_ASSERT()'類似的功能(可用於我)將是可以接受的,如果它是合理的。如果類型更改爲強制某人查看代碼,那麼我可以打破編譯。但是可能很重要的一點是,typeof不是我在所有我所針對的編譯器中可用的東西。

我專門找C語言的解決方案,所以模板是不是在這裏的任何使用...

+1

如果您對編譯器特定的方法開放,那麼您應該指定您的編譯器(或編譯器)...... – AnT 2011-06-06 23:44:09

+0

特定於編譯器與「合理便攜」不兼容。 – 2011-06-06 23:46:39

+0

我正在尋找'合理的便攜式',但是我應該指定編譯器,因爲我可能能夠使用預處理器來適應某些'足夠好'的工作:IAR,MSVC和GCC是我感興趣的。 – 2011-06-06 23:58:47

回答

2

這通常是由編譯指示控制。對於MSVC,你有#pragma warning,對於GCC,你有diagnostic pragmas(它確實不允許像MSVC一樣對警告進行細粒度的控制,但這就是你所擁有的)。

兩者都允許推/拉機制僅更改幾行代碼的警告。

+0

還有'_Pragma'(GCC)和'__pragma'(MSVC),它們在功能上與'#pragma'相同,但可用於宏的定義。 – 2011-06-06 23:55:13

+2

'_Pragma'實際上是C99,而不是gcc。 – 2011-06-07 00:05:58

6

如果 some_typedef不知道未簽名或簽名,我認爲你幾乎沒有運氣。

如果你事先知道some_typedef是無符號,你可以只使用

#if LOWER_BOUND > 0 
    return ((LOWER_BOUND <= val) && (val <= UPPER_BOUND)); 
#else 
    return ((val <= UPPER_BOUND)); 
#endif 

或在這種情況下,你可以使用我的首選版本:

return (val-LOWER_BOUND <= UPPER_BOUND-LOWER_BOUND); 

編輯:我假設some_typedef不是特定的符號,那麼UPPER_BOUNDLOWER_BOUND必須都是正數。否則,你會從some_typedef被提升爲無符號的結果非常古怪的結果。因此,你總是可以安全地使用:

return ((uintmax_t)val-LOWER_BOUND <= UPPER_BOUND-LOWER_BOUND); 
+0

我實際上開始認爲你的第一句話是最正確的。除了當我在幾個月內再次看到代碼時,我會花一些時間來弄清楚它在做什麼,除非我記住成語(我可能不會這樣做),但是對'首選版本'有一定的吸引力,而更直接的測試完全沒有考慮到要檢查什麼。我必須更多地考慮STATIC_ASSERT是否可以提供幫助,或者我應該決定是否有人更改typedef,他們需要對這種變化可能會如何影響負責。 – 2011-06-07 06:08:04

+1

我使用的成語一開始可能有點奇怪,但它實際上有很多非常好的應用程序。例如,如果你正在測試一個範圍列表的值,你可以用1個比較/每個範圍的分支而不是2個(我說一個列表,因爲我假設一個硬編碼範圍的編譯器可以使等價的優化)。這對理解無符號算術也很有指導意義。因此,這是一個我喜歡使用和推廣的習慣用法。 :-) – 2011-06-07 15:20:31

0

與其試圖消除警告,爲什麼不做一些事情並避免typedef擺在首位?您可以使重載來處理特定的情況,並通過避免隱藏警告來更明確地聲明您正在處理您正在處理的案例。根據我的經驗,這往往會迫使你測試新的代碼,而不是掩蓋未來可能發生的事情(比如突然改變數據類型,然後不得不處理預期範圍內的神祕值)。

+0

你如何在C中重載? – JeremyP 2011-06-07 10:37:41

1

我想出了一個非常簡單直接的解決方案。複製下界變量使編譯器停止抱怨:

#define LOWER_BOUND 0 
#define UPPER_BOUND 42 

int is_value_in_range(some_typedef val) 
{ 
    some_typedef lowerbound = LOWER_BOUND; 

    return ((lowerbound <= val) && (val <= UPPER_BOUND)); 
} 

我預計,在優化的編譯,編譯器將仍然能夠輕鬆擺脫不變的比較(我得驗證,但)。

+0

我懷疑如果編譯器的警告生成變得更聰明,警告將會回來。 – 2012-09-19 17:36:18

相關問題