[英]Accessing array by pointers
let int * ptr,array[10]; ptr= array;
int * ptr,array[10]; ptr= array;
。 現在,陣列連續位置中的每個存儲單元都具有固定大小。 如果第一個單元格的地址為1234,則下一個單元格的地址必須為1238。 但是我們使用指針作為*(ptr+1)
來訪問它。 我對此感到困惑。 有任何資料或答案嗎? 謝謝。
根據C11 標准: §6.5.2.1
表達式后跟方括號[]是數組對象元素的下標名稱。 下標運算符[]的定義是E1 [E2]與(*((E1)+(E2)))相同。 由於適用於二進制+運算符的轉換規則,如果E1是一個數組對象(相當於一個指向數組對象的初始元素的指針),而E2是一個整數,則E1 [E2]指定E1的第E2個元素E1(從零開始計數)。
EG您在做什么基本上是[]
已經在做什么
另外(相同的標准)解釋了為什么指針會如您注意到的那樣遞增:§6.5.6
將具有整數類型的表達式添加到指針或從指針中減去時,結果將具有指針操作數的類型。 如果指針操作數指向數組對象的元素,並且數組足夠大,則結果指向與原始元素偏移的元素,以使結果數組元素和原始數組元素的下標之差等於整數表達式。 換句話說,如果表達式P指向數組對象的第i個元素,則表達式(P)+ N(相當於N +(P))和(P)-N(其中N的值為n)表示到數組對象的第i + n個元素和第i-n個元素(如果存在)。 此外,如果表達式P指向數組對象的最后一個元素,則表達式(P)+1指向數組對象的最后一個元素之后,如果表達式Q指向數組對象的最后一個元素之后,表達式(Q)-1指向數組對象的最后一個元素。 如果指針操作數和結果都指向同一數組對象的元素,或者指向數組對象的最后一個元素之后,則求值不應產生溢出; 否則,行為是不確定的。 如果結果指向數組對象的最后一個元素之后,則不應將其用作被評估的一元*運算符的操作數。
編譯器知道ptr
是指向4字節類型的指針,因此它知道ptr+1
在內存中還有4個字節。
如果您想一會兒,很顯然這一定是這樣,否則您將無法在不知道(例如)系統中整數大小的情況下編寫可移植代碼。
此外,數組索引是幕后的精確指針算法-也就是說, array[3]
與*(array + 3)
完全相同
在為指針建立索引時,編譯器知道索引應按單元格的大小(在這種情況下為4字節的指針)前進。
指針算術考慮指針類型的大小。 例如,如果ptr
值為1234
,則由於ptr
的類型為int*
,則p + 1
值為1234 + 1 * sizeof(int) == 1234 + 1 * 4 = 1238
(假設sizeof(int) == 4
)。
+運算符的右側操作數(稱為x)不是您要移動指針的實際量。 因為int是4個字節,所以編譯器知道實際上會跳到x * 4。
指針算術的單位是指向對象,而不是字節。
如果p
指向int
對象,則p+1
, p+2
和p+3
指向連續的int
對象,而不是連續的字節。 如果p
指向大型結構,則它們指向該結構的連續實例。
編譯器在后台進行工作,將指針算法轉換為機器地址算法。 因此,它會根據需要乘以偏移量,以將對象單位轉換為字節單位。
我的猜測是,根據您的意見(ptr + 1)
應該會給您1235
但顯然沒有。
除了其他人為什么將其加4
並給您1238
的答案外,請考慮是否給了1235
,在1235
您沒有整數元素(即數組的第二個元素)。 但是您的指針應該指向一個整數。 因此,這種方式行不通。
指針算術是與普通算術不同的運算。 在指針算術中,一個參數必須是指針類型,另一個參數必須是整數類型:
intA + intB
:正常算術,結果為和。 intA + pointerB
:指針算術,執行的計算為sizeof(*pointerB)*intA + pointerB
pointerA + intB
:指針算術,執行的計算為pointerA + sizeof(*pointerA)*intB
pointerA + pointerB
:非法 pointerA[intB]
只是情況2( pointerA + intB
)的簡寫,這就是為什么它等效於intB[pointerA]
(解決情況3)的原因,但這僅在IOCCC中使用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.