c中的多维数组

时间:2012-08-10 12:05:41

标签: c multidimensional-array

请解释第一个和最后一个printf语句的输出。我认为他们应该提供相同的输出。

int main()
{
   char arr[5][7][6];
   char (*p)[5][7][6] = &arr;

   printf("%d\n", (&arr + 1) - &arr);
   printf("%d\n", (char *)(&arr + 1) - (char *)&arr);
   printf("%d\n", (unsigned)(arr + 1) - (unsigned)arr);
   printf("%d\n", (unsigned)(p + 1) - (unsigned)p);

   return 0;
}

输出:

1
210
42
210

4 个答案:

答案 0 :(得分:4)

让我们先看看内存布局:

char arr[5][7][6];此处arr是一组数组数组。

它将被安排到内存中,如下所示:

+--------------+ 
|              | arr[0]
+--------------+
|              | arr[1]
+--------------+
|              | arr[2]
+--------------+
|              | arr[3]
+--------------+

etc.

现在arr[i]char的数组数组。

所以a[i]就像

+--------------+  a[i][0]
|              |
+--------------+
|              |  a[i][1]
+--------------+
|              |  a[i][2]
+--------------+
|              |  a[i][3]
+--------------+

etc

现在arr[i][j]chars的数组。

所以

+--------------+ 
|              | arr[i][j][0]
+--------------+
|              | arr[i][j][1]
+--------------+ 
|              | arr[i][j][2]
+--------------+

etc.

编译器将在其符号表中创建一个名为arr的条目,并使用其第一个块的地址,并跟踪总大小(5 * 6 * 7 = 210个字节)。

现在是表达式

printf("%d\n", (&arr + 1) - &arr);

它是一个指针算术。所以它必然会键入每个符号。

让我们看看这一点。

(gdb) p &arr
$1 = (char (*)[5][7][6]) 0x7fffffffe160

您会看到arr的类型是指针char (*)[5][6][7]

换句话说,它指向数组数组的指针。指针算术实际上与指针所指向的类型有关。所以重要的是这种类型的大小。

(gdb) p sizeof(char [5][7][6])
$2 = 210

因此任何指向类型char [5][6][7]的指针都将递增或递减,如下所示:

&arr+1 => 0x7fffffffe160 +0xd2 => 0x7fffffffe232

(&arr + 1) - &arr => 0x7fffffffe232 - 0x7fffffffe160=> 0xd2

现在它实际返回 0xd2 。但对于指针算术,它意味着1*sizeof(char [5][7][6]) => 1

指针算术返回number of sizeof(type)而不是实际的字节偏移量。

您的

结果正确无误
printf("%d\n", (char *)(&arr + 1) - (char *)&arr);

因为你正在使它成为一个char指针。因此指针算术将使用1字节大小的单位sizeof(char)。因此输出将是210。

printf("%d\n", (unsigned)(arr + 1) - (unsigned)arr);

表达式中的arr将衰减为char (*)[7][6],因此它是指向二维数组的指针。它指向的类型大小为6 * 7 = 42.这就是你得到的结果。

printf(“%d \ n”,(无符号)(p + 1) - (无符号)p);

此处,p+1 - p将导致指针算术1 * sizeof(char(*)[5][6][7])。所以在指针运算中,它应该返回1.但是由于你将结果转换为无符号,它将放弃指针运算并使用整数运算。由于使用整数运算,它将处理大数字的指针值,因此您将获得实际的字节偏移量。

答案 1 :(得分:2)

如果它们被视为指针,它们将打印相同的结果,但在最后printf中,您强制它们通过强制转换被视为无符号整数。因此,在整数算术规则之后减去p + 1p,而不是指针算术规则。

修改

让事情变得更加清晰:

  • 当你减去2个指针时,结果就是元素的数量 它们之间。在你的情况下,它们之间有1个元素
  • 当您将指针转换为unsigned时,您告诉编译器 “这些只是简单的数字,没有什么可看的”。所以编译器对待 地址为数字,只是减去它们。

答案 2 :(得分:0)

第一个获取arr的地址并添加一个,然后减去地址,结果显然为1.

最后一个,p是指向char [5][7][7]的指针,使用(*p)[x][y][z]可以是p[0][x][y][z]。因此,(p + 1)可以被视为p[1],距离5 * 7 * 6为210(p}个字节。

如果你(((unsigned) p) + 1) - ((unsigned) p)那么那就是1

答案 3 :(得分:0)

地址之间的距离是1个元素或210个字节

第一张打印件打印元素数量 最后一个 - 字节数