【问题标题】:2d arrays memory map in CC中的二维数组内存映射
【发布时间】:2015-10-02 17:44:10
【问题描述】:

我一直在用 C 中的 2D 数组做各种问题。每个问题就像在我头上敲了另一个椰子,因为每个问题都使用不同的方法。例如,有些使用“取 2D 数组(如 a[2][4 ]),现在这会创建两个数组,其中一个数组的大小为 2,包含二维数组每一行的地址(就像这样有两行,每行四个值)“。而其他方法将其视为连续的一维数组表示。现在使用哪种方法。适当的内存映射会很有帮助。下面是锻炼的示例问题。

int main()
{ 
   unsigned int x[4][3] = {{1, 2, 3}, {4, 5, 6}, 
                           {7, 8, 9}, {10, 11, 12}};
   printf("%u, %u, %u", x+3, *(x+3), *(x+2)+3);
}

output:2036,2036,2036

现在,如果是第一种方法,为什么x+3和*(x+3)的地址是一样的?

【问题讨论】:

  • 内存布局是一个由 12 个连续整数组成的块。如果您改用数组索引表示法,您可能能够更好地回答您自己的问题。请记住,*(a+b) 表示 a[b]。所以您正在打印&x[3]&x[3][0]&x[2][3]。其中第一个是数组的地址,另外两个是 int 的地址。
  • %p 地址,.....

标签: c arrays memory multidimensional-array


【解决方案1】:

C 语言中的内置数组总是使用“第二种”方法(根据您的编号),没有例外。每次您声明 1D、2D、3D 或任何 D 数组时,就像在您的示例代码中一样,该数组在内存中布局为一个连续的内存块 - 作为“组合”大小的 1D 数组(即所有大小相乘)。

“第一种”方法只能用于“手动”组装的数组(所谓的“锯齿状”或“参差不齐”的数组)。该语言不会使用这种方法来表示显式声明的多维数组。

但是,使用%u 格式说明符打印指针值是未定义的行为。别这样了。函数printf提供%p格式打印指针。

x + 3 表达式中,unsigned [4][3] 类型的对象x 隐式衰减为unsigned (*)[3] 类型的值——一个指向x[0] 子数组的指针。根据指针算术规则,x + 3 是指向x[3] 子数组的unsigned (*)[3] 类型的值。

同样的事情最初发生在*(x + 3) 表达式中,除了x + 3(同样指向x[3] 子数组)被* 运算符取消引用并成为x[3] 子数组本身。在print 参数的上下文中,此子数组立即衰减为指向x[3][0]unsigned * 类型的值。

所以,即使x + 3*(x + 3) 的结果类型不同,它们仍然指向内存中完全相同的位置。这就是为什么指针值在数字上看起来相同的原因。

下面这个简单的例子也会发生同样的事情

int main()
{
  int a[10];
  printf("%p %p\n", (void *) &a, (void *) &a[0]);
}

输出将显示两个指针的相同数值。你的例子有点复杂,但本质上是一样的。

【讨论】:

  • 能否请您解释一下this.if可能的内存映射的上述问题。 @蚂蚁
猜你喜欢
  • 2011-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多