C - 两列3D数组之间的地址差异

时间:2018-01-25 08:06:54

标签: c arrays

以下C代码段,

int a[2][3][2] = { { {1,2},{3,4},{5,6} },{{7,8},{9,10},{11,12} } };
printf("%d %d",a[1]-a[0],a[1][0]-a[0][0]);

此代码提供输出3 6,但我没有得到这个。

我可以将3D数组a[2][3][2]可视化为两个大小为3x2的2D数组,其索引如下:

a[0][0]--> | 1 2 || 7  8 | <--a[1][0]  
a[0|[1]--> | 3 4 || 9  10|
           | 5 6 || 11 12|
            a[0]    a[1]

假设a[0]的地址为1000a[1]的地址为1012,假设int的大小为2个字节。 所以(a[1] - a[0])应该是12,但它给出的3. 3实际上是矩阵中的行数。但是,要获得行数,代码应该是这样的:

(a[1] -a[0])/(row_size *sizeof(int));

同样,在a[1][0]-a[0][0]

的情况下

我不明白这件事。 请解释。 谢谢。

2 个答案:

答案 0 :(得分:9)

让我们尝试写出数组在内存中的样子:

+------------+------------+------------+------------+------------+------------+------------+------------+------------+------------+------------+------------+
| a[0][0][0] | a[0][0][1] | a[0][1][0] | a[0][1][1] | a[0][2][0] | a[0][2][1] | a[1][0][0] | a[1][0][1] | a[1][1][0] | a[1][1][1] | a[1][2][0] | a[1][2][1] |
+------------+------------+------------+------------+------------+------------+------------+------------+------------+------------+------------+------------+
^                         ^                         ^                         ^
|                         |                         |                         |
a[0][0]                   a[0][1]                   a[0][2]                   a[1][0]
|                                                                             |
a[0]                                                                          a[1]

当你这样做的时候a[1] - a[0]你让子数组衰减为指针到它们的第一个元素,两个指针之间的差异以它们的解引用类型为单位。

因此,对于a[0](和a[1]),类型为int [3][2]。它衰减到指向其第一个元素的指针,该元素的类型为int (*)[2]。解除引用的指针将是int [2]类型。现在int [2]a[0]之间有多少a[1]?有三个这样的元素,因此a[1] - a[0]的结果是3

如果我们选择a[1][0] - a[0][0],则a[1][0]a[0][0]的类型均为int [2]。它衰减为int *类型的指针,解除引用的类型为intinta[0][0]之间有六个a[1][0]元素。

答案 1 :(得分:2)

根据standard 6.5.6p9,这是未定义的行为:

  

当减去两个指针时,两个指针都指向同一个数组对象的元素,或者指向数组对象的最后一个元素; 结果是两个数组的下标的差异元素。结果的大小是实现定义的,它的类型(有符号整数类型)是在头文件中定义的ptrdiff_t ...

问题是它会在大多数系统中产生预期的效果。但请注意a[0]a[1]属于同一个数组a。但是a[0][0]a[1][0]属于不同的数组对象,然后指针将指向违反上述规则的两个不同的数组对象。这就是未定义行为的原因。