C语言 C 数组如何在内存中表示?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7844049/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How Are C Arrays Represented In Memory?
提问by Daniel Scocco
I believe I understand how normal variables and pointers are represented in memory if you are using C.
如果您使用 C,我相信我了解普通变量和指针在内存中的表示方式。
For example, it's easy to understand that a pointer Ptr will have an address, and its value will be a different address, which is the space in memory it's pointing to. The following code:
例如,很容易理解一个指针 Ptr 会有一个地址,它的值会是一个不同的地址,也就是它指向的内存空间。以下代码:
int main(){
int x = 10;
int *Ptr;
Ptr = &x;
return 0;
}
Would have the following representation in memory:
在内存中会有以下表示:
+---------------------+-------------+---------+
| Variable Name | Address | Value |
+---------------------+-------------+---------+
| x | 3342 | 10 |
+---------------------+-------------+---------+
| Ptr | 5466 | 3342 |
+---------------------+-------------+---------+
However I find it difficult to understand how arrays are represented in memory. For example the code:
但是我发现很难理解数组在内存中的表示方式。例如代码:
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;
}
outputs the same address twice (for the sake of simplicity 10568). Meaning that x==&x. Yet *x (or x[0] in array notation) is equal to 12, *(x+1) (or x[1] in array notation) is equal to 13 and so on. How can this be represented? One way could be this:
两次输出相同的地址(为简单起见,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 |
+---------------------+-------------+----------+----------------------+
Is this close to what happens, or completely off?
这接近发生的事情,还是完全关闭?
回答by caf
An array is a block of contiguous objects with no spaces in between. This means that xin your second example is represented in memory as:
数组是一组连续的对象,中间没有空格。这意味着x在您的第二个示例中在内存中表示为:
+---------------------+-------------+---------+
| Variable Name | Address | Value |
+---------------------+-------------+---------+
| x | 10568 | 12 |
| | +---------+
| | | 13 |
| | +---------+
| | | 14 |
| | +---------+
| | | ?? |
| | +---------+
| | | ?? |
+---------------------+-------------+---------+
That is, xis five ints big, and has a single address.
也就是说,x是 5 ints 大,并且有一个地址。
The weird part about arrays isn't in how they're stored - it's how they're evaluated in expressions. If you use an array name somewhere that it isn't the subject of the unary &or sizeofoperators, it evaluates to the address of its first member.
关于数组的奇怪部分不在于它们的存储方式——而是它们在表达式中的计算方式。如果您在某处使用不是一元&或sizeof运算符主题的数组名称,则计算结果为其第一个成员的地址。
That is, if you just write x, you will get a value 10568 with type int *.
也就是说,如果你只写x,你会得到一个类型为 10568 的值int *。
If, on the other hand you write &x, then the special rule doesn't apply - so the &operator works like it normally does, which means that it fetches the address of the array. In the example, this will be a value 10568 with type int (*)[5].
另一方面,如果你写了&x,那么特殊规则不适用——所以&操作符像往常一样工作,这意味着它获取数组的地址。在示例中,这将是一个类型为 10568 的值int (*)[5]。
The reason that x == &xis that the address of the first member of an array is necessarily equal to the address of the array itself, since an array starts with its first member.
原因x == &x是数组的第一个成员的地址必须等于数组本身的地址,因为数组从它的第一个成员开始。
回答by Raymond Chen
Your diagram is correct. The weirdness around &xhas nothing to do with how arrays are represented in memory. It has to do with array->pointer decay. xby itself in value context decays into a pointer to its first element; i.e., it is equivalent to &x[0]. &xis a pointer to an array, and the fact that the two are numerically equal is just saying that the address of an array is numerically equal to the address of its first element.
你的图是对的。周围的怪异&x与数组在内存中的表示方式无关。它与数组->指针衰减有关。x自身在值上下文中衰减为指向其第一个元素的指针;即,它等价于&x[0]。&x是一个指向数组的指针,并且两者在数值上相等的事实只是说数组的地址在数值上等于其第一个元素的地址。
回答by Schwern
Yes, you've got it. A C array finds the indexed value x[y]by calculating x + (y * sizeof(type)). xis the starting address of the array. y * sizeof(type)is an offset from that. x[0]produces the same address as x.
是的,你明白了。AC 数组x[y]通过计算找到索引值x + (y * sizeof(type))。 x是数组的起始地址。 y * sizeof(type)是一个偏移量。 x[0]产生与 x 相同的地址。
Multidimensional arrays are similarly done, so int x[y][z]is going to consume sizeof(int) * y * zmemory.
多维数组也是类似的,所以int x[y][z]会消耗sizeof(int) * y * z内存。
Because of this you can do some stupid C pointer tricks. It also means getting the size of an array is (almost) impossible.
正因为如此,你可以做一些愚蠢的 C 指针技巧。这也意味着(几乎)不可能获得数组的大小。
回答by Sinan ünür
The Arrays and Pointers section in the C FAQhas some helpful information.
C FAQ 中的数组和指针部分提供了一些有用的信息。
回答by Tharindu Rusira
Daniel,
丹尼尔,
this is not difficult. You have the basic idea and there's no much difference in memory representation of arrays. if you declare an array, say
这并不困难。你有基本的想法,数组的内存表示没有太大区别。如果你声明一个数组,说
void main(){
int arr[5]={0,1,2,3,4};
}
you have initialized(defined) the array. So the five elements will be stored in five adjacent locations in memory. you can observe this by referencing the memory address of each element. Not like other primitive data types in C, an array identifier(here, arr) itself represents its pointer. The idea seems vague if you are a beginner but you will feel comfortable as you go on.
您已经初始化(定义)了数组。所以这五个元素将存储在内存中的五个相邻位置。您可以通过引用每个元素的内存地址来观察这一点。与 C 中的其他原始数据类型不同,数组标识符(此处为arr)本身表示其指针。如果您是初学者,这个想法似乎很模糊,但随着您的学习,您会感到很舒服。
printf("%d",arr);
this line will show you the memory address of the first element, arr[0]. This is similar to referencing the address of the first element.
这一行将显示第一个元素 arr[0] 的内存地址。这类似于引用第一个元素的地址。
printf("%d",&arr[0]);
now, you can view memory locations of all elements. The following piece of code will do the job.
现在,您可以查看所有元素的内存位置。以下代码将完成这项工作。
int i;
for(i=0;i<5;i++){
printf("location of %d is %d\n",arr[i],&arr[i]);
}
you will see each address increments by gaps of four.(if your integers are 32 bits long). So you can easily understand how the arrays are stored in the memory.
您将看到每个地址的增量为 4。(如果您的整数是 32 位长)。所以你可以很容易地理解数组是如何存储在内存中的。
you can also try the same thing using a different method.
你也可以用不同的方法尝试同样的事情。
int i;
for(i=0;i<5;i++){
printf("location of %d is %d\n",*(a+i),a+i);
}
you will get the same set of answers in both cases and try to get the equivalence.
在这两种情况下,您将得到相同的一组答案并尝试获得等效性。
try the same experiment using different data types(char, float and struct types). You will see how the gaps between adjacent elements vary based on the size of a single element.
使用不同的数据类型(char、float 和 struct 类型)尝试相同的实验。您将看到相邻元素之间的间隙如何根据单个元素的大小而变化。


回答by alex
An array in C is a sequential block of memory with each member's block of the same size. This is why pointers work, you seek an offset based on the first member's address.
C 中的数组是一个连续的内存块,每个成员的块大小相同。这就是指针起作用的原因,您根据第一个成员的地址寻找偏移量。
回答by ObscureRobot
A C array is just a block of memory that has sequential values of the same size. When you call malloc(), it is just granting you a block of memory. foo[5]is the same as *(foo + 5).
AC 数组只是一块具有相同大小的连续值的内存块。当您调用 malloc() 时,它只是授予您一块内存。foo[5]与 相同*(foo + 5)。
Example - foo.c:
示例 - 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);
}
Output:
输出:
$ ./foo
&foo[0]: 5fbff5a4
foo: 5fbff5a4
&foo[3]: 5fbff5b0
foo: 5fbff5b0
回答by Anonrandom
int x[] produces the same result as int* x;
int x[] 产生与 int* x 相同的结果;
it's just a pointer
它只是一个指针
therefore notations x[i] and *(x + i) produce the same result.
因此符号 x[i] 和 *(x + i) 产生相同的结果。

