2014-03-06 14 views
1

如何重新編寫代碼來執行相同的測試,但便攜式避免警告?如何在沒有警告的情況下測試`int`到`size_t`的轉換「比較始終爲真」?


AFAIK,INT_MAXSIZE_MAX沒有定義一個總是爲> =比其他的,因此以下功能的使用,以檢測問題轉換從intsize_t

#include <assert.h> 
#include <stddef.h> 
#include <stdint.h> 

size_t int_to_size_t(int size) { 
    assert(size >= 0); 

    #pragma GCC diagnostic ignored "-Wtype-limits" 

    // Without the above pragma, below line of code may cause: 
    // "warning: comparison is always true due to limited range of data type 
    // [-Wtype-limits]" 
    assert((unsigned)size <= SIZE_MAX); 

    #pragma GCC diagnostic warning "-Wtype-limits" 

    return (size_t) size; 
} 

不同的編譯器使用各種機制來壓制警告。我尋找一種便攜式解決方案。

以上解決方案不是便攜式的,但這種方法不幸有副作用:警告-Wtype-limits,現在可能已啓用或可能未啓用,現在在此代碼後啓用。不知道如何恢復-Wtype-limits設置。

編號:
Portability of #warning preprocessor directive
Suppress comparison always true warning for Macros?

+0

注意:使用4.8.2 gcc和「gcc -std = c99 -O1 -g3 -pedantic -Wall -Wtratra -Wconversion」。希望它能在許多編譯器上工作。 – chux

回答

7

你可以取代這個:

assert((unsigned)size <= SIZE_MAX); 

由:

#if INT_MAX > SIZE_MAX 
assert((unsigned)size <= SIZE_MAX); 
#endif 

如果#if條件是假的,assert條件始終爲真和assert是不必要的。 (unsigned)轉換(可能)需要避免關於有符號和無符號操作數之間的比較的警告。

警告:我沒有測試過這個。 (爲了完全測試它,我需要訪問系統int寬於size_t,我從來沒有見過這樣的系統。)

+1

BTW:在關於擺脫警告的答案中愛「警告:...」。 :-) – chux

+0

我認爲你們兩個比較有點不對,請看我的答案。 –

+0

1)我重新測試瞭解決方案,並在2個編譯器上運行(AFAIK)。 (我最初的測試是有缺陷的。)2)是的,演員陣營要安靜地警告有關已簽名和未簽名的操作數。 – chux

2

由於基思說得對,你只需要擔心值的INT_MAX大於SIZE_MAX。如果您想在預處理器中比較這些值(而且您應該),則無法強制使INT_MAX爲無符號類型。 (預處理器不知道關於強制轉換。)

因此,您必須將0U添加到值中,以使兩個表達式都變爲uintmax_t。 (對於預處理器整數常量是intmax_tuintmax_t)。

#if (INT_MAX+0U) > SIZE_MAX 
assert(size <= (int)SIZE_MAX); 
#endif 

那麼這裏面#if你知道SIZE_MAX是小於INT_MAX,所以你可以將它轉換到int不改變價值。

+1

我不認爲'+ 0U'是必要的。就預處理器而言,「INT_MAX」的類型爲「intmax_t」,「SIZE_MAX」的類型爲「uintmax_t」。 '<'運算符將'intmax_t'操作數轉換爲'uintmax_t',然後比較這兩個操作數。 –

+0

@凱斯湯普森,沒有一個演員是「必要的」。關於簽名類型如何轉換爲未簽名類型有很好的規則,這裏沒有真正的問題。問題是過度保護的編譯器,預處理器部分中的僞轉換可以避免這種情況。 –

+0

好的,演員可以避免警告 - 但實驗表明gcc,至少不會在預處理器表達式中對有符號比較和無符號比較提出警告。也許其他編譯器更挑剔。 –

相關問題