2014-11-20 78 views
3

問題是這樣的:禁用「警告:‘x’的地址將始終評估爲‘真’」

#define do_stuff(ret) ((ret) ? getstuff(ret) : 0) 
int var; 
do_stuff(&var); 

test.h:34:46: warning: the address of 'var' will always evaluate as 'true' [-Waddress] 

do_stuff作爲一個接受的輸出指針,可以爲NULL的功能,雖然,因此警告沒有幫助,但煩人。 有沒有辦法通過代碼讓gcc停止抱怨?也許(至少是一種)便攜式的?

Btw。 do_stuff必須是一個宏,因爲ret實際上是以通用方式設置的(這裏爲簡單起見而被剝離)。

編輯: 同樣,我只想有通常的輸出指針,可以是NULL,但在一個宏而不是函數。實際的代碼如下所示:

#define retrieve(x, ret) \ 
    (ret ? (*ret = x.buf[0], 1) : 0) 

使用它像retrieve(stuff, NULL)時給了警告,從上面。因此,以阿德里亞諾Repetti的回答,我把它改爲:

#define retrieve(x, ret) \ 
    (((void *)ret != NULL) ? (*ret = x.buf[0], 1) : 0) 

其作品,但現在給了我warning: dereferencing 'void *' pointer,因爲這被擴大到(((void *)NULL != NULL) ? (*NULL = x.buf[0], 1) : 0)。我有辦法擺脫這種警告嗎?

retrieve具有是一個宏因爲x.buf是變型的,所以是ret,使其通過一個函數像的尖端會導致類型的損失。

+0

你是什麼意思「'ret'實際上是以通用方式設置的」?它總是一個'int *'?如果不是,你可以在函數原型中使用'void *'嗎? – Degustaf 2014-11-20 20:19:16

+0

像「只有宏能做到這一點」 - 通用,如果我使用了一個'void *',我需要'memcpy',這會降低代碼的速度。 – netcat 2014-11-20 20:32:54

+0

var的內容可能爲0/NULL,但是變量的地址,特別是堆棧中的地址總是非零值。所以編譯器是正確的。也許你真正想要的是傳遞var變量的內容(通過值傳遞)。如果是這樣,那麼從調用關於最後編輯的宏 – user3629249 2014-11-20 22:41:55

回答

4

假設你真的不能避免宏觀和考慮,我不會禁用警告(即使這尤其是一個不危險),那麼我欺騙編譯一些轉換。代碼將是便攜和無警告會發出:

#define do_stuff(ret) (((uintptr_t)NULL != (uintptr_t)ret) ? getstuff(ret) : 0) 

中央位置點很簡單:(uintptr_t)NULL != (uintptr_t)ret。我建議在SO上閱讀this post。請注意,也只是NULL != (void*)ret的作品。

+1

這是爲什麼downvoted? – 2501 2014-11-20 20:13:05

+0

@ 2501我不知道......我希望他/她會解釋! – 2014-11-20 20:13:34

+0

你使用什麼編譯器?這似乎是依賴於編譯器的,我保留'!= NULL'的警告,但是沒有警告'(uintptr_t)NULL!=',並且我的方法沒有警告。 – 2501 2014-11-20 20:26:44

2

您可以添加一個虛擬函數,只是返回的指針,這可能壓制編譯:

void* pass(void* a) 
{ 
    return a ; 
} 

#define do_stuff(ret) (pass(ret) ? getstuff(ret) : 0) 
int var; 
do_stuff(&var); 
+0

謝謝,這也適用。然而,鑄造增加了更少的混亂。 – netcat 2014-11-20 20:41:27

2

GCC的-Waddress命令行標誌用於禁用此類型的警告。但是最好在沒有警告的情況下編寫代碼。

1

正如尤金噓說,這是更好地編寫代碼,而不警告,

所以不是這個

#define do_stuff(ret) ((ret) ? getstuff(ret) : 0) 

void getstuff(int *ptr) 
{ 
    printf("%d\n", *ptr); 
} 

int main(void) 
{ 
    int var = 5; 
    do_stuff(&var); 
} 

你能做到這一點

void getstuff(int *ptr) 
{ 
    if (ptr == NULL) 
     return; 

    printf("%d\n", *ptr); 
} 

int main(void) 
{ 
    int var = 5; 
    getstuff(&var); 
} 

所以最好不要隱藏NULL反正檢查宏。如果一個函數帶有一個允許爲NULL的指針,那麼NULL檢查應該在函數本身中是明確的。