"array" 个元素值是存储在一个位置还是不同的位置?

Are "array" element values stored in one location or in separate locations?

因为C语言中没有数组,下面是全部存储在一个内存位置,还是每个元素的值都存储在"array"个内存位置?

int array[] = {11, 13, 17, 19};

哪个是有效的内存布局?

C 将 "array" 明确定义为一种类型。

引用 C11,章节 §6.2.5,类型(强调我的

An array type describes a contiguously allocated nonempty set of objects with a particular member object type, called the element type. The element type shall be complete whenever the array type is specified. Array types are characterized by their element type and by the number of elements in the array. An array type is said to be derived from its element type, and if its element type is T, the array type is sometimes called ‘‘array of T’’. The construction of an array type from an element type is called ‘‘array type derivation’’.

简而言之,答案是数组元素存储在单独但连续的位置。

假设我们声明了一个包含 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 + 1C == B + 1等。

这里,请注意,指针运算与数据类型有关,因此A+1不会导致地址增加1byte,而是增加1element .换句话说,两个连续元素的地址之间的差异将与数据类型的大小相同(sizeof (datatype))。

元素将位于连续内存位置。

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

编译器在特定的连续位置分配数组。

您也可以使用下一个代码进行检查:

#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 的大小。


一般来说,你可以把指针指向数组的一个元素,比如说索引m,然后把它作为元素数添加n,然后得到指向[=15]的指针=]数组中的索引。

*(array + n) == array[n]

Since there's no such thing as an array in the C language

C语言中完全有数组这种东西。你所有的例子都是 C 数组。

您描述的区别是 listarray 之间的区别。

C 中的数组,实际上在大多数语言中,就像您的 Scenerio 1。

您当然可以使用一组指向值的指针来完成您的 Scenerio 2。例如

int array1[] = {11, 14, 17, 19};
// vs 
int* array2[] = {
    &array1[0],
    &array1[1],
    &array1[2],
    &array1[3]
};

A 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;
    }
} 

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 的指针),而 &arrayint(*)[4] 类型(指向 4 个整数的数组的指针)。