由于C语言中没有数组这样的东西,以下所有内容都存储在一个内存位置,或者每个元素的值都存储在"数组中。内存位置?
int array[] = {11, 13, 17, 19};
情景1
{11, 13, 17, 19} --> location A
情景2
{
11 --> location A
13 --> location B
17 --> location C
19 --> location D
}
哪一个是有效的内存布局?
答案 0 :(得分:7)
C明确将“数组”定义为类型。
引用C11
,章节§6.2.5,类型(强调我的)
数组类型描述了一个连续分配的非空对象集 特定的成员对象类型,称为元素类型。元素类型应为 指定数组类型时完成。数组类型的特点是它们的 元素类型和数组中元素的数量。据说是一种数组类型 从其元素类型派生,如果其元素类型为T,则有时是数组类型 称为''T'数组'。调用元素类型的数组类型的构造 ''数组类型推导''。
简而言之,答案是,数组元素存储在不同但相邻的位置。
假设我们已经声明了一个5 int
的数组:
int arr[5];
然后,在一个整数大小为2个字节(szeof(int) ==2
)的平台上,该数组的元素组织如下:
在sizeof(int) == 4
的不同平台上,可能是:
所以代表
{
11 --> location A
13 --> location B
17 --> location C
19 --> location D
}
有效,考虑B == A + 1
,C == B + 1
等。
请注意,指针算法会考虑数据类型,因此A+1
不会产生1 byte
增量的地址,而是增量为element
。换句话说,两个连续元素的地址之间的差异将与数据类型(sizeof (datatype)
)的大小相同。
答案 1 :(得分:3)
元素将位于连续内存位置。
让array[0]
位于B位置,数组中每个元素的大小(即sizeof(int)
)为S.然后我们就有了这个
array[0] at B
array[1] at B + S
array[2] at B + 2S
..
array[n] at B + n*S
答案 2 :(得分:1)
编译器在特定的连续位置分配数组。
您还可以使用下一个代码进行检查:
#include <stdio.h>
void main()
{
int array[] = {11, 13, 17, 19};
for (int i = 0; i < 4; i++)
printf("0x%p ", &array[i]);
}
这给出了十六进制地址
0x14fee0 0x14fee4 0x14fee8 0x14feec
每个元素的边距为4个字节,大小为int。
通常,您可以将指针指向数组的一个元素,例如index m
,并将其添加为n
作为多个元素,并获取指向n+m
的指针数组中的索引。
*(array + n) == array[n]
答案 3 :(得分:1)
C确实有一个数组类型。仅仅因为你可以通过指针访问数组并不意味着它们不存在。
数组元素存储在从地址“array”开始的连续内存位置(即array
的基址,也是数组的第一个元素的地址),并且数组的每个元素都是可寻址的分开。
假设4个字节的整数,数组int array[] = {11, 13, 17, 19};
看起来像:
+-----+-----+-----+-----+
| 11 | 13 | 17 | 19 |
+-----+-----+-----+-----+
^ ^ ^ ^
0x100 0x104 0x108 0x112
您可以通过简单的程序更好地理解:
#include <stdio.h>
int main(void)
{
int array[] = {11, 13, 17, 19};
/* all will print the same value */
printf("Base address of array: %p, %p, %p\n", (void*)array, (void*)&array[0], (void*)array);
for (size_t i = 0; i < sizeof array/sizeof array[0]; i++) {
printf("address of array[%d]: %p\n", i, (void*)&array[i]);
}
return 0;
}
一个重要的细节是,虽然地址&array[0]
和&array
是相同的值,但它们的类型是不同的。 &array[0]
的类型为int*
(指向int的指针),而&array
的类型为int(*)[4]
(指向4个整数的数组的指针)。
答案 4 :(得分:0)
因为C语言中没有数组这样的东西
在C语言中完全存在数组这样的东西。您的所有示例都是C数组。
您所描述的差异是list
和array
之间的差异。
C中的数组,就像大多数语言一样,就像你的Scenerio 1。
你当然可以通过一系列指向数值的指针来完成Scenerio 2。例如
int array1[] = {11, 14, 17, 19};
// vs
int* array2[] = {
&array1[0],
&array1[1],
&array1[2],
&array1[3]
};
但是list
在组织方面有很大不同。
struct list_node{
int value;
struct list_node * next;
};
struct int_list {
int length;
struct list_node * first;
};
int main(){
int i;
struct list_node nodes[4];
struct int_list list1 = {.length = 4, .first=&nodes[0]};
for (i = 0; i < 4; i++){
nodes[i].value = array1[i];
if (i != 3){
nodes[i].next = &nodes[i+1];
} else {
nodes[i].next = NULL;
}
}
// traverse the list.
struct list_node * n = list1.first;
while(n != NULL){
printf("%d\n", n->value);
n = n->next;
}
}