2015-10-14 168 views
12

下面兩個鑄件有什麼區別嗎?鑄造虛空指針

int a=10; 
int *p=&a; 

(void)p;   //does not give any warning or error 

(void *)p;  //error: statement with no effect [-Werror=unused-value] 

gcc -Wall -Werror --std=c99 -pedantic

Just saw that in this answer.遵守(顯然我誤解的東西)

回答

11

是的,很明顯。

(void)p; 

意味着對象得到澆鑄到void類型,(這不是一個完整的類型),並且是完整的表達式,該表達式的結果不應該被使用的,因此編譯器不檢查它的使用。

引用C11標準,章節6.3.2.2,void

一個void表達(即具有類型空隙的表達)的(不存在的)值不應 以任何方式被使用,[... ...]如果任何其他類型的表達式被評估爲void 表達式,則其值或指示符將被丟棄。

因此,不會產生警告或錯誤。

OTOH,

(void *)p; 

表示對象是一個指向void類型,這是一個完整的類型,因此應該在程序中使用。在這種情況下,編譯器正確地報告不在表達式中使用對象。

+0

由'p'指向的地址前的鑄造值是否有任何變化? – ameyCU

+0

@ameyCU nopes。只有在有副作用的情況下,纔會生效,而這種情況並非如此。 –

+0

並且再次將'p'轉換爲'int *'將會安全嗎? – ameyCU

14

當你

(void) p; 

你告訴編譯器根本不顧表達p的結果。這實際上是相同的空語句:

; 

當你

(void *) p; 

你告訴編譯器把變量p作爲一種通用的指針,而這對於充分表達聲明,這個表達式並沒有真正做任何事情,並且你得到錯誤信息。

+0

你可以給這個功能一些真實世界的使用嗎? –

+1

@DavidHaim:我曾經在某些只在'IFDEF'內部使用某些局部變量的情況下看到了它,以便在使用帶有'ELSE'分支的設置進行編譯時不會引發警告。 –

+0

大聲笑,所以聲明ELSE分支內的局部變量,如果它是唯一觸及它的地方。或者我想它是從一個時期開始的,你可以在範圍的開始處聲明所有的變量.. –