int a[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} };
A:a[0][0]
返回值1,取地址后&a[0][0]
返回的是一个int*
类型的指针,加上5后指针往后走5个元素,因为数组是按行存储的,因此最后指向元素6,也就是a[1][1]
的地方,解引用就得到6
B:a[1]
其实等价于*(a + 1)
,那么a[1][1]
等价于*(*(a + 1) + 1)
,a[1][1][1]
等价于*(*(*(a + 1) + 1))
。。。以此类推
C:a[1]
返回一个int*
类型的指针,再对这个指针取地址&a[1]
,会得到一个int (*p)[4]
,即一个指向含有4个元素数组的指针,本例中指向数组{5, 6, 7, 8}
,对这个指针加1,那么这个指针会指向下一个数组{9, 10, 11, 12}
,即一次走了4个元素(这里注意int*
指针加的操作和int (*p)[4]
指针加的操作的区别,前者每+1就往后走一个元素,后者+1就往后走四个元素),最后解引用得到的是一个指向元素9的int*
型的指针,也就是a[2][0]
,因此错误,而且就算要得到a[2][0]
,也应该解引用两次**(&a[1]+1)
D:同样的,可以写成*(*(a + 1) + 1)
,和B相同
A. *(&a[0][0] + 5):这个表达式通过取 a[0][0] 的地址并加上 5,然后使用间接引用运算符 * 来访问该地址的值。由于 a[0][0] 是二维数组的第一个元素,所以它的地址加上 5 实际上是 a[1][1] 的地址,因此这个表达式可以表示 a[1][1]。
B. ((a+1) + 1):这个表达式先将 a 的地址加上 1,得到 a[1] 的地址,然后再将该地址加上 1,得到 a[1][1] 的地址。使用间接引用运算符 * 可以访问该地址的值,因此这个表达式也可以表示 a[1][1]。
D. *(a[1] + 1):这个表达式先获取 a[1] 的地址,然后将该地址加上 1,得到 a[1][1] 的地址。使用间接引用运算符 * 可以访问该地址的值,所以这个表达式同样可以表示 a[1][1]。
选项 C. (&a[1] + 1):这个表达式通过取 a[1] 的地址并加上 1,然后使用间接引用运算符 * 来访问该地址的值。这里的问题在于,a[1] 是一个长度为 4 的一维数组,(&a[1] + 1) 的结果将是 a[2] 的地址,而不是 a[1][1] 的地址。因此,选项 C 不能表示 a[1][1]。