2011-07-23 85 views
18

我想到的是這樣的:可以在printf中使用指向字符串的指針嗎?

#include <stdio.h> 
#include <conio.h> 
#include <stdlib.h> 

int main(void) { 
    //test pointer to string 
    char s[50]; 
    char *ptr=s; 
    printf("\nEnter string (s): "); 
    fgets(s, 50, stdin); 
    printf("S: %s\nPTR: %s\n", s, *ptr); 

    system("PAUSE"); 
    return 0; 
} 

或者我應該用一個for循環與*(S + i)和格式說明%C? 這是通過指針和簡單的printf打印字符串的唯一可能的方法嗎?

更新:printf與數組的第一個元素的地址一起操作,所以當我使用* ptr時,我實際上使用第一個元素操作而不是它的地址。謝謝。

+15

請不要使用'gets'。 「不要使用gets(),因爲如果事先不知道數據,就不可能知道get()將讀取多少個字符,並且由於gets()會繼續存儲緩衝區末尾的字符,所以對於它已被用於破壞計算機安全,請使用fgets()代替。「 (['與fgets(3)'](http://linux.die.net/man/3/fgets))。 –

+6

如果您不介意,我會調整代碼以最大限度地減少評論您寫的內容對問題不重要的機率。即使用'gets()'和'main()'的返回類型。你應該不惜一切代價避免使用'gets()'並且使用其他方法,比如'fgets()'(就像@Bertrand解釋的那樣)。 'main()'應該_always_返回'int'。 –

回答

32

"%s"格式說明符printf總是預計有一個char*參數。

考慮:

char s[] = "hello"; 
char *p = "world"; 
printf("%s, %s\n", s, p); 

看起來像要傳遞的第一%s的陣列和第二的指針,但實際上你(正確地)傳遞兩個指針。

在C中,陣列類型的任何表達式隱式轉換的指針數組的第一元素除非它是在以下三個上下文之一:

  • 這是一個參數傳遞給一元「&」 (address-of)運算符
  • 它是一元「sizeof」運算符的參數
  • 它是用於初始化數組對象的初始值設定項中的字符串文字。

(我認爲C++有一個或兩個其它的異常。)

printf()實施看到"%s",假定對應參數是一個字符指針,並使用該指針來遍歷串和打印它。

comp.lang.c FAQ的第6部分對此進行了很好的討論。

+0

關於「數組類型的任何表達式被隱式轉換爲指向數組的第一個元素的指針」 - 雖然這是真的,但是內存明智的程序會爲'p'變量分配4或8字節(依賴於平臺)來存儲'w '字符,但's'變量不是這種情況。由於編譯器知道數組總是出現在連續的內存塊中,所以's'能夠像編譯器一樣充當指針。對於存儲「h」字符地址的's'變量,不會發生單獨的內存分配。請糾正我,如果我有任何錯誤的位。 – RBT

+1

我不會說''''能夠表現爲[a]指針「。 's'是一個數組對象。表達式's'在大多數情況下是一個指針表達式。對於'char * p =「world」;','sizeof(char *)'字節被分配給'p',並且6字節被分配給與字符串相對應的數組對象。你是對的,沒有單獨的內存分配爲's'完成;聲明'char s [] =「hello」;'不創建一個指針對象。 –

+0

爲什麼我說「s能夠表現爲[a]指針」是因爲printf的「%s」格式說明符始終需要char *參數,而s是數組對象,它仍然足以滿足參數的期望:)。但我明白你的觀點。當它實際上是一個數組對象時,我們不應該調用's'的指針。 – RBT

6
printf("%s\n", ptr); 

這是你想要的嗎?

順便說一句,從printf(3),這裏是爲s轉換符(即%s)的文檔:

如果沒有l修飾符是迄今:爲const char *參數預計 是指向字符類型數組的指針(指向字符串的指針)。 數組中的字符被寫入(但不包括)終止空字節('\ 0')的 ;如果指定精度,則不會寫入比指定的數字更多的 。如果給出了精度,則不需要存在空字節 ;如果未指定精度或者數組大小大於 ,則該數組必須包含終止空字節的 。

+0

對不起,我只是重新編輯了腳本 –

+0

,實際上'printf(「%s \ n」,* ptr);' –

+3

@AndrewGH:Betrand Marron是對的。 '* ptr'具有'char'類型,但'%s'需要'char *'類型,所以'printf(「%s \ n」,ptr);'是正確的。 –

1

你應該做的 「printf(」 S:%S \ NPTR:%S \ n 「S,PTR); 」的printf的(而不是「 S:%S \ NPTR:%S \ n」 ,s,* ptr); PTR和* PTR之間

區別是:PTR給你地址在你指向的變量的內存和* PTR給予相當的尖銳的變量在這種情況下的是* PTR = PTR [0]

這個代碼將說明我的意思:

printf("\tS: %s\n\tPTR: %s\n\tAddress of the pointed Value: %x\n\tValue of the whole String: %s\n\tValue of the first character of the String: %c\n", s, ptr,ptr,ptr,*ptr); 
+0

是的,當然,但是,當使用'printf(「%s」,array_name)'你基本上訪問&array_name [0],是不是這樣?...哦,不要我知道了。 printf使用數組第一個元素的地址來操作,所以當我使用* ptr時,我實際上是使用第一個元素來操作,而不是它的地址。謝謝。 –

+0

@Andrew G.H:printf(「%s」,array_name)不允許您訪問&array_name [0],而是訪問&array_name。&array_name是特定類型的變量的地址。處理每個變量的方式因類型而異。對於字符串(char *)%array_name,但是對於像你說的第一個字符,但由於「%s」,printf必須讀取array_name直到找到'0' – arthur

+0

數組的標識符等於地址數組的第一個元素:'array_identifier ==&array_identifier [0]'http://www.cplusplus.com/doc/tutorial/pointers/ –

0

根據我的經驗,當您嘗試使用%s指令* p時應該出現分段錯誤。