簡體   English   中英

K&R:字符指針數組

[英]K&R: array of character pointers

在pg。 K&R的109,我們看到:

void writelines(char *lineptr[], int nlines)
{
  while (nlines -- > 0) printf("%s\n", *lineptr++);
}

我對* lineptr ++究竟做了什么感到困惑。 根據我的理解,printf需要一個char指針,所以我們用* lineptr提供。 然后我們將lineptr增加到數組中的下一個char指針? 這不是非法的嗎?

在頁99,K&R寫道“數組名稱不是變量;結構如a = pa [其中a是數組,pa是指向數組的指針]和++是非法的。”

繼續閱讀! 在p的最底部。 99

作為函數定義中的形式參數,

  char s[]; 

  char *s; 

是等價的; 我們更喜歡后者,因為它更明確地說參數是一個指針。

即你永遠不能將數組(不是變量)傳遞給函數。 如果你聲明一個看起來像是一個數組的函數,它實際上需要一個指針(這一個變量)。 這是有道理的。 函數參數不是變量會很奇怪 - 每次調用函數時它都可以有不同的值,所以它肯定不是常量!

lineptr實際上不是一個數組; 它是指向指針的指針。 請注意,postincrement運算符++優先級高於解除引用運算符* ,因此lineptr++會出現這樣的情況:

  1. lineptr遞增以指向數組中的下一個元素
  2. 的結果lineptr++是的舊值lineptr ,即一個指針陣列中的當前元素
  3. *lineptr++取消引用,因此它是數組中當前元素的值

因此,while循環遍歷由lineptr指向的數組中的所有元素(每個元素都是一個char* )並將它們打印出來。

可能更容易想象*lineptr++如下:

*(lineptr++)

在那里,指向char* s數組的指針被移動到數組的下一個元素,即從lineptr[0]移動到lineptr[1] (由於指針的后綴增量,在解除引用后會出現指針的增量。)

所以基本上,發生以下事情:

  1. lineptr[0]char*類型)通過lineptr[0]檢索。
  2. 指針遞增到數組的下一個元素。 (通過指針lineptr上的后綴增量。)
  3. 指針現在指向lineptr[1] ,再次從步驟1開始重復該過程。

Adam Rosenfield的精選答案是錯誤的。 還有coobird的答案。 出於這個原因,我投了兩個答案。

Adam Markowitz對*lineptr++解釋是對的,但他沒有回答主要問題,這是否是合法的C99代碼。 只有湯姆未來呢; 不幸的是他沒有解釋*lineptr++ 我給了他們一個點。

簡而言之, lineptr是一個變量,可以作為指針進行操作。 因此增加指針是合法的。

lineptr是指向字符序列的指針序列的指針。 換句話說,它是指向字符串數組的第一個字符串的指針。 根據代碼,我們可以假設字符串是null('\\ 0')終止的char序列。 nlines是數組中的字符串數。

while測試表達式是nlines-- > 0 nlines--是一個后減量(因為--在變量的右邊)。 因此,在執行測試之后執行並且無論測試結果如何,因此在任何情況下都執行。

因此,如果作為參數給出的nlines值為0 ,則首先執行測試並返回false ; 循環中的指令不會執行。 請注意,由於nlines無論如何都會遞減, while循環后的nlines值將為-1

如果nlines == 1 ,則測試將返回true並且nlines將遞減; 循環中的指令將執行一次。 請注意,執行這些指令時, nlines值為0 當再次執行測試時,我們回到nlines == 0時的情況。

printf指令使用*lineptr++表達式。 它是指針的后增量( ++位於變量的右側)。 這意味着首先計算表達式,並在使用執行增量。 因此,在第一次執行時, printf接收字符串數組的第一個元素的副本,該元素是指向字符串的第一個字符的指針。 lineptr僅在此之后遞增。 下一次執行printflineptr指向第二個元素,並在第二個字符串打印時移動到第三個元素。 這很有道理,因為我們顯然想要打印第一個字符串。 如果Adam Rosenfield是對的,那么第一個字符串就會被跳過,最后我們會嘗試將字符串打印到最后一個字符串之外,這顯然是一件壞事。

因此, printf指令是以下兩個指令的簡明形式

printf("%s\n", *lineptr);
++lineptr; // or lineptr++, which is equivalent but not as good. lineptr += 1; is ok too.

請注意,根據經驗,當前后增量在其動作中是等效的時,出於性能原因,預增量是優選的。 編譯器會為您切換它。 好吧,大部分時間。 對於預操作員來說,只要有可能,它就更好,所以它總是被使用。 一旦你自己在C ++中實現后期和預先增量,原因就變得更加明確了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM