簡體   English   中英

如何在內存中代表C陣列?

[英]How Are C Arrays Represented In Memory?

我相信如果你使用C,我理解在內存中如何表示正常的變量和指針。

例如,很容易理解指針Ptr將具有一個地址,並且它的值將是一個不同的地址,這是它指向的內存空間。 以下代碼:

int main(){
    int x = 10;
    int *Ptr;
    Ptr = &x;
return 0;
}

將在內存中具有以下表示:

+---------------------+-------------+---------+
| Variable Name       | Address     | Value   | 
+---------------------+-------------+---------+
| x                   | 3342        | 10      |
+---------------------+-------------+---------+
| Ptr                 | 5466        | 3342    |
+---------------------+-------------+---------+

但是我發現很難理解數組如何在內存中表示。 例如代碼:

int main(){
    int x[5];
        x[0]=12;
        x[1]=13;
        x[2]=14;

    printf("%p\n",(void*)x);
    printf("%p\n",(void*)&x);

return 0;
}

輸出相同的地址兩次(為簡單起見10568)。 意思是x ==&x。 然而,* x(或數組符號中的x [0])等於12,*(x + 1)(或數組符號中的x [1])等於13,依此類推。 怎么能代表這個? 一種方法可能是這樣的:

+---------------------+-------------+----------+----------------------+
| Variable Name       | Address     | Value    | Value IF array       |
+---------------------+-------------+----------+----------------------+
| x                   | 10568       | 10568    | 12                   |
+---------------------+-------------+----------+----------------------+
|                     | 10572       |          | 13                   | 
+---------------------+-------------+----------+----------------------+
|                     | 10576       |          | 14                   | 
+---------------------+-------------+----------+----------------------+
|                     | 10580       |          | trash                | 
+---------------------+-------------+----------+----------------------+
|                     | 10584       |          | trash                | 
+---------------------+-------------+----------+----------------------+

這接近發生的事情還是完全關閉?

數組是一個連續對象塊,中間沒有空格。 這意味着第二個示例中的x在內存中表示為:

+---------------------+-------------+---------+
| Variable Name       | Address     | Value   | 
+---------------------+-------------+---------+
| x                   | 10568       | 12      |
|                     |             +---------+
|                     |             | 13      |
|                     |             +---------+
|                     |             | 14      |
|                     |             +---------+
|                     |             | ??      |
|                     |             +---------+
|                     |             | ??      |
+---------------------+-------------+---------+

也就是說, x為五點int的大,並且有一個地址。

關於數組的奇怪部分不在於它們是如何存儲的 - 它們是如何在表達式中進行評估的。 如果在某處使用數組名稱,它不是一元&sizeof運算符的主題,則它將計算其第一個成員的地址。

也就是說,如果你只是寫x ,你將得到一個類型為int *的值10568。

另一方面,如果你寫&x ,那么特殊規則不適用 - 所以&運算符就像通常那樣工作,這意味着它獲取數組的地址。 在示例中,這將是類型為int (*)[5]的值10568。

x == &x的原因是數組的第一個成員的地址必須等於數組本身的地址,因為數組以其第一個成員開頭。

你的圖表是正確的。 圍繞&x的怪異與如何在內存中表示數組無關。 它與array->指針衰減有關。 x本身在值上下文中衰減為指向其第一個元素的指針; 即,它相當於&x[0] &x是指向數組的指針,並且兩者在數值上相等的事實只是說數組的地址在數值上等於其第一個元素的地址。

是的,你已經明白了。 AC陣列通過計算x + (y * sizeof(type))找到索引值x[y] x是數組的起始地址。 y * sizeof(type)是一個偏移量。 x[0]產生與x相同的地址。

多維數組類似地完成,因此int x[y][z]將消耗sizeof(int) * y * z內存。

因此,你可以做一些愚蠢的C指針技巧。 這也意味着獲得數組的大小(幾乎)是不可能的。

AC數組只是一塊具有相同大小的連續值的內存塊。 當你調用malloc()時,它只是給你一塊內存。 foo[5]*(foo + 5)

示例 - foo.c:

#include <stdio.h>

int main(void)
{
    int foo[5];
    printf("&foo[0]: %tx\n", &foo[0]);
    printf("foo: %tx\n\n", foo);
    printf("&foo[3]: %tx\n", &foo[3]);
    printf("foo: %tx\n", foo + 3);
}

輸出:

$ ./foo
&foo[0]: 5fbff5a4
foo: 5fbff5a4

&foo[3]: 5fbff5b0
foo: 5fbff5b0

C中的數組是一個順序的內存塊,每個成員的塊大小相同。 這就是指針工作的原因,你根據第一個成員的地址尋找偏移量。

C FAQ中Arrays and Pointers部分提供了一些有用的信息。

丹尼爾,

這並不困難。 你有基本的想法,並且數組的內存表示沒有太大區別。 如果你聲明一個數組,比如說

     void main(){
         int arr[5]={0,1,2,3,4};


     }

你已經初始化(定義)了數組。 因此,五個元素將存儲在內存中的五個相鄰位置。 你可以通過引用每個元素的內存地址來觀察它。 與C中的其他原始數據類型不同,數組標識符(此處為arr )本身表示其指針。 如果你是初學者,這個想法似乎含糊不清,但隨着你的繼續,你會感到很舒服。

      printf("%d",arr);

這一行將顯示第一個元素的內存地址arr [0]。 這類似於引用第一個元素的地址。

      printf("%d",&arr[0]);

現在,您可以查看所有元素的內存位置。 以下代碼將完成這項工作。

    int i;
    for(i=0;i<5;i++){
       printf("location of %d is %d\n",arr[i],&arr[i]);
    } 

你會看到每個地址以4的間隙遞增。(如果你的整數是32位長)。 因此,您可以輕松了解數組如何存儲在內存中。

你也可以嘗試使用不同的方法做同樣的事情。

    int i;
    for(i=0;i<5;i++){
       printf("location of %d is %d\n",*(a+i),a+i);
    }

在這兩種情況下,你都會得到同樣的答案,並嘗試獲得等價。

嘗試使用不同的數據類型(char,float和struct類型)進行相同的實驗。 您將看到相鄰元素之間的間隙如何根據單個元素的大小而變化。

int x []產生與int * x相同的結果;

它只是一個指針

因此,符號x [i]和*(x + i)產生相同的結果。

暫無
暫無

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

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