2013-04-25 49 views
4

有沒有一種很好的方法來擺脫以下警告?我知道這是一個類型問題,我通過了unsigned long pointer而不是unsigned long,但printf支持指針作爲參數嗎?我身上的迂腐者想擺脫這種警告。如果不是,你如何處理與printf打印解除引用的指針值?printf指針參數類型警告?

#include <stdio.h> 

int main (void) { 
    unsigned long *test = 1; 
    printf("%lu\n", (unsigned long*)test); 
    return 0; 
} 

警告:格式指定鍵入「無符號長」,但參數的類型爲

回答

11
unsigned long *test = 1; 

是無效的。如果你想有一個指針的值1一個對象,你可以這樣做:

unsigned long a = 1; 
unsigned long *test = &a; 

或使用C99化合物字面:

unsigned long *test = &(unsigned long){1UL}; 

現在也:

printf("%lu\n", (unsigned long*)test); 

不正確。實際上,你想:

printf("%lu\n", *test); 

打印unsigned long對象*test的價值。

要打印test指針值(以實現定義的方式),你需要:

printf("%p\n", (void *) test); 
+0

這實際上會產生一個警告:一個不兼容的整數指針轉換初始化 – EhevuTov 2013-04-25 21:21:09

+1

@EhevuTov這是從'unsigned long * test = 1;'行。 – 2013-04-25 21:22:29

+0

%p產生指針的地址。我想要的是實際的去參考值,應該是'1' – EhevuTov 2013-04-25 21:25:19

0

你不是真的需要強制轉換test,而%p將採取任何指針(甚至雖然規範說它需要一個void *)。使用%p轉換說明符是通過printf打印指針最安全(也是令人驚訝的,最便攜的)機制。

#include <stdio.h> 

int main (void) { 
    unsigned long ul = 1; 
    unsigned long *test = &ul; 
    printf("%p\n", test); 
    return 0; 
} 

編輯:哦,是的,而且要小心嘗試使用類型,如intlong等依靠自己的字號。這是依賴於實現的,並且可以(並且確實)在這些平臺的不同平臺和編譯器上進行更改。 C標準只是說long必須至少與int一樣大。 POSIX standard for printf「長度修飾符」不以位爲單位指定大小,而是按C類型指定大小。因此,你不能假定sizeof(long) == sizeof(void*)(好吧,他們在Linux內核中做了這個假設,但它總是與gcc結合,總是這樣)。

+0

這是我得到的更多,但它返回的地址,而不是值 – EhevuTov 2013-04-25 21:32:57

+3

實際上,'%p'需要一個'void *',並傳遞它一個不同的指針類型調用未定義的行爲。如果你傳遞一個指針,它實際上有一個不同於'void *'的表示,事情可能真的會破壞。 – 2013-04-25 21:33:30

+0

那麼,從技術上說,規範說明了一個指向void的指針,但是如果你理解可變參數的實現方式,那並不重要。但是,我想這確實會進入實現定義的領域(編譯器)。這就是爲什麼gcc不會發出警告,因爲它不能告訴它是什麼類型的指針,只是它是一個指針。不過,我會更新我的答案以反映這一點。但就看到奇怪的結果而言,我很想知道實際發生的實例(平臺,編譯器等)。 – 2013-04-25 21:40:47