二维数组的内存映射



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

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)的地址是相同的?

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

"first"方法只能用于"手动"组装数组(即所谓的"锯齿"或"粗糙"数组)。该语言不会使用这种方法来表示显式声明的多维数组。

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

x + 3表达式中,unsigned [4][3]类型的对象x隐式衰减为指向x[0]子数组的指针unsigned (*)[3]类型的值。根据指针算术规则,x + 3是一个unsigned (*)[3]类型的值,它指向x[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 %pn", (void *) &a, (void *) &a[0]);
}

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

相关内容

  • 没有找到相关文章

最新更新