簡體   English   中英

[]運算符如何工作?

[英]How does the [] operator work?

我正在使用C,但是我認為這是一個更底層的問題,與語言無關。

程序如何使用array [0]或array [6]正確地獲取正確的數據,而不管它保存的數據類型是什么? 它在內部存儲長度還是要尋找某種分隔符?

編譯器知道基礎數據類型的sizeof ,並將正確的字節偏移量添加到指針。

a[10]等效於*(a + 10) ,后者等效於*(10 + a) ,后者又等效於10[a] ,沒有開玩笑。

編譯器在編譯時計算出大小,並在目標代碼中對大小進行硬編碼。

除了直接回答外,我還想提供一些其他信息。

在Dennis Ritchie的C歷史主頁上有一篇有趣的文章,其中有很多關於數組,數組索引等方面的文章。

這可能不會直接回答您的問題,但可能會使您對C數組有進一步的了解。

都不:-)

對於數組,編譯器知道:(a)數組開始的地址,以及(b)數組包含什么類型的元素(int,float,double等),以及每個元素的長度。

利用這兩條信息,找到array[6]是一個簡單的算法問題:從基地址開始,再加上元素大小的6倍。

編譯器將替換在編譯時固定的數據類型的長度。

int getInt(void * memory, offset)
{
     return *((int *)(sizeof(int)*offset + memory))
}

void * chunkOfMemory = malloc(0x1000);
int * intarray = (int *) chunkOfMemory;
printf("%d is equal to %d", getInt(chunkOfMemory, 9), intarray[9]);

編譯器在編譯時知道數組每個元素的大小。 例如:

int64_t array[5];
...
int64_t a = array[3];

這將被轉換為偽匯編代碼:

addr <- array
addr <- addr + 3 * sizeof(int64_t)
//                 ^^^^^^^^^^^^^^^ which the compiler knows is 8
//             ^^^^^^^^^^^^^^^^^^^ which the compiler can replace with 24.
a <- *addr 

數組的長度無關緊要。

這是編譯器的魔力

編譯器知道數組元素的大小,並使用它來計算正確的地址。

是的,您是對的,甚至更低級的問題,甚至匯編器都有[]運算符。 這個答案說的很好,但我的解釋是:

arr[x]*((void *)(&arr) + x * sizeof(arr[0]))

看起來有點復雜,但是生成的代碼很簡單。 這是因為編譯器知道sizeof(arr[0])並且在編譯代碼中進行了硬編碼,而且(void *)(&arr)只是一種語言標准,可以保護程序員免受愚蠢的錯誤,並且在編譯代碼中沒有類型轉換。

正如我提到的低級語言一樣,還有一件事需要提高。 使用它們,您可以重載運算符,並使它做您想做的任何事情。

不,不是。 它只是在地址array + X*sizeof(TypeOfArrayEl)處獲取/設置元素,因此您可以輕松地越界,並且那時沒有人會給您錯誤。 這就是為什么array[6]6[array]相同的原因

假設數組的類型為int:

int array[12];

[]運算符將括號內的任何值(乘以數組類型的字節大小)乘以括號外的值。 數組由實現存儲為指向其第一項的指針。 因此,上面的數組聲明分配了12 * sizeof(int)個字節,並使array指向第一個。 這會導致像3[array]這樣的古怪的東西給您3[array]的第三個元素。

無論如何,問題的答案是編譯器在編譯時查看數組的類型,然后將[]中的值乘以數組持有的類型的大小。

據我所知,如果索引超出范圍,C不會給您一個編譯時錯誤。 即使您超出范圍,指針也只會為您提供下一個相鄰的存儲位置。 C唯一需要照顧的是增加多少字節的指針。 如果它是一個整數數組,則指針將針對索引中的每個增量前進2個字節,對於char類型的指針將遞增1個字節。

您始終可以訪問超出范圍但是垃圾數據的位置,而作為程序員,您必須確保訪問的數據正確。

我猜這就是自由的代價:)

暫無
暫無

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

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