2010-07-28 126 views
7

當我們談論解除引用時,是否有必要使用*呢?如果我們訪問指針所指的一些其他的方式,可以將其視爲解引用指針或沒有,如:爲什麼printf(「%s」,ptr)能夠解引用void *?

char *ptr = "abc" ; 
printf("%c" , *ptr); // Here pointer is dereferenced. 
printf("%s" , ptr); // What about this one? 

這是我的問題的第一部分。

現在如果printf("%s" , ptr)是解引用的示例,那麼也請回答我的問題的以下部分。

ķ& [R說

a "pointer to void" is used to hold any type of pointer but cannot be dereferenced itself

因此,

char a = 'c' ; 
char *p = &a ; 
void *k = &a; 
printf("\n%c\n" , *p); 
printf("\n%c\n" , *k); 

不能編譯,編譯器給出錯誤

In function ‘main’: warning: dereferencing ‘void *’ pointer error: invalid use of void expression

但是如果我們用

char *a = "c" ; 
char *p = a ; 
void *k = a; 
printf("\n%c\n" , *p); 
printf("\n%s\n" , k); 

它編譯和工作。這意味着無效指針可以被解除引用 - 我們已經得到了對象指針指向的內容。
如果是這種情況,那麼上面提到的K & R是什麼意思?

謝謝你的時間。

+1

我沒有看到你在哪裏解除引用'void *'成功。請重新閱讀您的代碼。 – leppie 2010-07-28 10:53:27

回答

9

不,你有什麼是「未定義的行爲」 - C語言標準沒有說明會發生什麼。在你的情況下,它「工作」,但對於另一個用戶/編譯器/平臺,它可能不是。您的發言:

printf("\n%s\n" , k); 

等同於:

int k = 42; 
printf("\n%s\n" , k); 

和同樣是不確定的。

+0

我明白了你的觀點。謝謝。問題的第一部分呢? 'printf(「%s」,ptr)'也被視爲指針的解引用? – 2010-07-28 10:59:18

+1

@andrew printf()肯定需要對指針進行取消引用,以完成對「%s」格式化程序的操作。 OTOH,如果您在同一個指針上使用「%p」格式化程序,則不需要遵守。 – 2010-07-28 11:01:24

+0

我不知道這個標準是如何定義'printf'的,或者我錯過了某些東西,但可以設想'void *'被轉換爲'char *',因爲'printf'可以推斷它是一個字符串由'%s'完成。然後再次,這個問題可能是一個可變參數問題。我不想挖掘它。 – 2011-10-25 01:02:11

0

在給出的例子:

char *a = "c"; 
char *p = a; 
void *k = a; 
printf("\n%c\n" , *p); 
printf("\n%s\n" , k); 

發生了什麼,在第一個printf,值「C」是從提領該char指針傳遞,printf只知道你給它一個char因爲%c格式標記。

現在,void*只是一個未知類型的原始指針,不能對其進行解引用,因爲除非將其轉換爲其他類型,否則編譯器不知道要從中讀取哪種類型。

在第二個printf中,void*指針被傳入。printf只是將其看作一個普通數字,並且不知道它是什麼,直到它讀取給定的格式標記。通過使用%s,你告訴printf函數,你實際上通過了一個char*,所以它會相應地轉換它,並以字符串的形式正確讀取它,即取消引用char*指針 - 而不是void*指針。

它是有效的代碼,只要void*指針指向以空值終止的char數組。如果void*指針指向不同的東西,printf函數仍然樂意嘗試將其讀取爲char*指針(如果指定了%s)並導致未定義的行爲。

不同的壞榜樣:

char *a = "ce"; 
int b = (int)a; 
printf("\n%s\n" , b); 

無法提領的整數下去,但我告訴printf,這是一個char*,所以它的工作原理。

相關問題