2011-08-15 88 views
1
#include <stdio.h> 

int main() 
{ 
char *arr = "This is to test"; 
printf("\n%c %c ",*(arr++), *(arr++)); 
return 0; 
} 

該程序輸出h T而不是輸出h h。爲什麼這樣?從字符指針打印字符

+4

兩個字:未定義的行爲(u)r –

+0

有沒有辦法輸出'hh' ...它可能輸出'h T'或'T h'(取決於沒有定義參數的評估順序),但'hh'只是沒有意義。 –

+2

我期望他認爲arr ++和arr + 1是一樣的。他沒有意識到++實際上修改了arr。 –

回答

5

ARR ++相當於給Arr + = 1.您實際上遞增ARR。這就是你的情況正在發生的事情。

printf("\n%c %c ",*(arr++), *(arr++)); 
//    ^  ^Evaluates to 0 therefore prints T then increments by 1 
//     ^Evaluates to 1 therefore prints h and then increments by 1 
//Now if where to prinf %s arr it should print "is is to test" 

你想要做什麼是

printf("\n%c %c ",*(arr+1), *(arr+1)); 

注:正如其他人所指出的多個前/後綴++/- 產生不確定的行爲(評估順序),應避免雖然我在你的情況瞭解你不是要修改原來的陣列。

+0

這並不回答爲什麼'h'在他的情況下'T'之前打印的問題。然而,它確實回答了他爲什麼不是'h''h'的問題的第二部分。 –

+0

我認爲它確實回答了爲什麼'h T'是輸出的問題。查看評論。 –

7

使用兩個增量運營商在一個聲明中是相互獨立的引線不確定的行爲,因爲編譯器可以自由選擇其遞增第一(或者說你沒有給編譯器任何暗示其中一個第一事要做)。

無論如何,如果你期待h h,這也是錯誤的寫*(arr++)兩次,因爲他們將兩個執行遞增arr兩次 - 所以會有印刷(arr[0]arr[1])兩個不同的角色。

另一個錯誤是使用後增量,這將導致arr後遞增字符已抓取,因此它會輸出T,不h

因此,一個可能的解決方案是這樣的代碼,用一個額外的變量:

#include <stdio.h> 

int main() 
{ 
char *arr = "This is to test"; 
char c = *(++arr); 
printf("\n%c %c ", c, c); 
return 0; 
} 

在此代碼,arr將只一次遞增,並且在該位置取出的字符以後可以使用。

1

基本上,因爲++在打印後將指針向前移動了一步,而且今天大多數編譯器生成的代碼最先完成。然後它會向左移動。

這是因爲一元運算符arr ++將導致arr = arr + 1;,因爲它使用的是後綴運算符,所以在將結果分配給arr之前將會打印它。

這樣執行的步驟是:

  1. 印花T
  2. 移動指針到h
  3. 打印^ h
  4. 移動指針到我

如果你有三個在同一行,你會得到IH T作爲這將導致其移動第三次。

我相信你正在嘗試做的是值得的效果:

printf("\n%c %c ",*(arr+1), *(arr+1)); 
+0

「以及今天大多數編譯器生成的代碼」我認爲這不是真正依賴於編譯器本身,而是來自架構上使用的調用約定(特別是從堆棧上的參數順序)。 –

1

如果u [R應該得到輸出h小時。 然後u必須寫

printf("\n%c %c",*(arr+1),*(arr+1)); 

但在這裏,在你的代碼更新改編,這是增量後增量所以首先它將該值賦給函數參數,然後變量遞增。從左至右堆棧分配的功能

printf("\n%c %c ",*(arr++), *(arr++)); 

值,這樣你們可以想像這樣下面的語句:

printf("\n%c %c ",'h', 'T'); 

和論證「\ N%C%C」將打印輸出從左正確的,你得到了輸出h T.