[英]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++
會出現這樣的情況:
lineptr
遞增以指向數組中的下一個元素 lineptr++
是的舊值lineptr
,即一個指針陣列中的當前元素 *lineptr++
取消引用,因此它是數組中當前元素的值 因此,while循環遍歷由lineptr
指向的數組中的所有元素(每個元素都是一個char*
)並將它們打印出來。
可能更容易想象*lineptr++
如下:
*(lineptr++)
在那里,指向char*
s數組的指針被移動到數組的下一個元素,即從lineptr[0]
移動到lineptr[1]
。 (由於指針的后綴增量,在解除引用后會出現指針的增量。)
所以基本上,發生以下事情:
lineptr[0]
( char*
類型)通過lineptr[0]
檢索。 lineptr
上的后綴增量。) 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
僅在此之后遞增。 下一次執行printf
, lineptr
指向第二個元素,並在第二個字符串打印時移動到第三個元素。 這很有道理,因為我們顯然想要打印第一個字符串。 如果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.