【问题标题】:how do arrays work internally in c/c++数组如何在 C/C++ 中内部工作
【发布时间】:2013-10-22 14:36:26
【问题描述】:

我想知道数组在 c 中是如何工作的。我最终得到一个假设,我想知道我是否正确。

我们知道数组是一系列相邻的内存盒(盒子),其中每个盒子都有它所存储的类型的大小(即,如果 INT 一个盒子的 size = sizeof(int) 并且包含 3 个 INT 的数组内存相邻位置 3 sizeof(int) )

现在我们也知道我们可以为特定类型的数组动态分配内存(C 中的 malloc,C++ 中的 new)。

让我想知道的是,当使用括号 [0] 调用数组时,数组的原点是数组第一个框的地址和第一个值(后面框中的值)是 array[ 0] == *(array+0) == *array(数组是否被声明为“type * array”或“type array[]”或“type array[size]”)和“array”以这种方式调用是否定义为指针或数组(“type * array”或“type array[]”或“type array[size]”)是第一个框的地址。

我最终想到,我想确认一下:即使用方括号 ([]) 声明的数组实际上在内存中也是一个 n 指针序列,每个指针都包含(作为值而不是地址)包含实际值的存储盒 Bi 的地址 + 那些存储盒(B0,...,Bn 每个都包含实际值)。这样,当一个人声明“int array[5]”时,程序实际上分配了 5 个相邻的 int 指针框 P0、P1、..、P4 和 5 个 int 大小的内存位置,分散在计算机内存 B0、B1 中。 ..,B4 其中Pi的值为Bi的地址

我是对还是错!!???谢谢!

【问题讨论】:

  • 不,除非您有 int *arr[],否则数组具有实际整数。
  • 阅读comp.lang.c FAQ的第6部分。

标签: c++ c arrays pointers memory


【解决方案1】:

即使用方括号 ([]) 声明的数组实际上在内存中也是一系列 n 个指针,每个指针包含 [...] 包含实际值的内存盒 Bi 的地址 + 那些内存盒

没有。

听起来您很困惑array[0] == *(array+0) == *array 对于声明为int array[10];int *array = ...; 的数组如何都为真。一个完全合理的问题;我们被告知,对于指针 ptr,表达式 *ptr 获取指针指向的值,所以当我们对数组使用相同的语法时,我们要取消引用的地址在哪里?

这是秘密:数组索引运算符 ([]) 不适用于 C 和 C++ 中的数组。当您将它应用于数组时,语言会隐式地将数组转换为指向数组第一个元素的指针。因此,添加到数组或取消引用数组似乎与添加或取消引用指针的行为相同。

int array[10];

// These lines do exactly the same thing:
int *ptr1 = &array[0]; // explicitly get address of first element
int *ptr2 = array;     // implicitly get address of first element

因此,数组实际上是内存中的一组连续元素,其中每个元素实际上都是值,而不是指向包含该值的另一​​个位置的指针。只是数组的定义方式意味着它们通常会隐式转换为指针,因此实际上只有隐式转换时似乎存在指针。

【讨论】:

  • “数组索引运算符 ([]) 不适用于数组。”当然可以。这就是它的用途。但是操作符的作用和指针加法是一样的。
  • @EJP 不,如果您阅读 C++ 规范,您会发现下标运算符仅用于处理“指向 T 的指针”类型的表达式,而不是数组类型的表达式。在数组上使用下标与在指针上使用它的原因是因为在数组上使用它首先将数组转换为指针,然后它实际上是相同的。
  • @EJP 另一种查看方式是,如果您在诸如 int main() { int array[10]; array[0]; } 的代码中使用 clang 中的 AST 转储功能,则 AST 将向您显示一个节点 ArraySubscriptExpr,该节点具有一个节点 ImplicitCastExpr <ArrayToPointerDecay>在左边。
【解决方案2】:

数组连续存储在虚拟内存中。但是,它们映射到的物理内存地址可能是连续的,也可能不是连续的。

并且数组元素不存储指向下一个元素的指针。只存储值。

【讨论】:

    【解决方案3】:

    可以这样想:

    array[n] 只是*(array + n) 的语法糖。

    不,没有指针,数组实际上包含连续内存范围内的值。

    【讨论】:

    • 是的,这就是我写的以及我是如何理解它的,但我的问题是当一个人执行“int array[n]”(或任何其他类型)时,内存分配会发生什么?
    • * 进行解引用,因此您从位置 n 获得 。如果您写的内容属实,则需要额外的取消引用步骤。 (但从符号中您可以清楚地看到没有)。
    • 您看到图片的绿色部分了吗?直接在那里写值。这就是发生的事情。实际分配取决于它是局部变量还是动态分配的变量。每个都有自己的(特定于实现)规则它不是特定于数组的。
    【解决方案4】:

    数组不包含任何指针。数组的元素存储在堆上,而对这些元素的引用存储在堆栈上。如果您声明一个名为 values 的数组,其类型为 int,它由 5 元素组成。

    变量values是指向存储在堆上的第一个值values[0]的指针,也称为基地址,即数组第一个元素的地址。您可能想知道代码如何找到数组的其他元素。 values[1] 可以通过*(values+1) 取消引用,或者在较低级别,就像这样*(&values + n*sizeof(values[0])) 其中n 是您要取消引用的元素的索引。

    因此,您只需将元素的大小添加到内存中即可获得数组的其他元素。这是因为数组的元素并排存储在内存中,或者从技术上讲,内存块共享相同的边界。

    数组没有任何指针,包含指针的类似数据结构的数组称为链表。

    您可以了解数组的内部工作here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多