无法按预期解除对多维数组的引用

时间:2019-01-09 02:57:19

标签: c arrays pointers multidimensional-array

int arr5[][3] = {{1,2,3}, {4,5,6}, {7,8,9}};

声明2D数组的变量包含指向第一个数组中第一个元素的指针。 arr5定义为每行3列。通过将arr5加1,我们获得第二行中第一个元素的地址,通过将2添加到arr5中,我们获得第三行中的第一个元素的地址。

int *row1 = arr5;
int *row2 = arr5 + 1;
int *row3 = arr5 + 2;

取消引用指向数组的指针将获取数组中的第一个元素。

printf("%d\n", *row1);  // prints 1
printf("%d\n", *row2);  // prints 4
printf("%d\n", *row3);  // prints 7

我们可以使用[]取消引用这些行中的元素。

for (j = 0; j < 3; j++) {
  printf("%d%c", row1[j], (j==2)?'\n':' ');
} // prints 1 2 3

我们可以不使用方括号打印第二行。现在,第2行保存第二行中第一个元素的地址。

for (j = 0; j < 3; j++) {
  printf("%d%c", *(row2+j), (j==2)?'\n':' ');
}  // prints 4 5 6

在上面的示例中,为什么不能用arr5 + 1代替row2? row2保留地址arr5 + 1。

for (j = 0; j < 3; j++) {
  printf("%d%c", *((arr5+1)+j), (j==2)?'\n':' ');
}  // prints what looks to be addresses

2 个答案:

答案 0 :(得分:4)

  

除非它是sizeof运算符的操作数,否则_Alignof   运算符,或者一元'&'运算符,或者是字符串文字   初始化数组,该表达式的类型为“数组类型”   转换为类型为“类型的指针” 的表达式   指向数组对象的初始元素,而不是   左值。 C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3)

因此,当您访问arr5时,实际上就是在使用指向int [3]数组的指针。。尝试分配时:

int *row1 = arr5;

您尝试将类型为arr5的{​​{1}}分配给int(*)[3]的{​​{1}},从而导致警告:

row1

要消除警告,您需要取消引用int*的类型"initialization from incompatible pointer type" (在访问时将其转换为指向行中第一个元素的指针),该类型与arr5兼容。例如,重新整理一下示例,可以执行以下操作:

int[3]

注意: int*#include <stdio.h> int main (void) { int arr5[][3] = {{1,2,3}, {4,5,6}, {7,8,9}}, *row1 = *arr5, *row2 = *(arr5 + 1), *row3 = *(arr5 + 2); size_t nrow = sizeof arr5 / sizeof *arr5, ncol = sizeof *arr5 / sizeof **arr5; puts ("By row:"); for (size_t j = 0; j < ncol; j++) /* output row1 */ printf ("%3d", *(row1 + j)); putchar ('\n'); for (size_t j = 0; j < ncol; j++) /* output row2 */ printf ("%3d", *(row2 + j)); putchar ('\n'); for (size_t j = 0; j < ncol; j++) /* output row3 */ printf ("%3d", *(row3 + j)); putchar ('\n'); puts ("\nBy array:"); for (size_t i = 0; i < nrow; i++) { /* output arr5 */ for (size_t j = 0; j < ncol; j++) printf ("%3d", *(*(arr5 + i) + j)); putchar ('\n'); } } 通常比等效的指针符号更具可读性)

使用/输出示例

row1[j]

仔细检查一下,如果还有其他问题,请告诉我。

答案 1 :(得分:3)

注意编译器警告。 *((arr5+1)+j)不是int,而是int *

  

警告:格式'%d'期望类型为'int'的参数,但是参数2的类型为'int *'[-Wformat =]

注意:(arr5+1)+j(arr5+1+j)相同。我怀疑OP想要*(arr5+1)+j在这里。

int main() {
    int arr5[][3] = {{1,2,3}, {4,5,6}, {7,8,9}};
    for (int j = 0; j < 3; j++) {
      printf("%d%c", *((arr5+1)+j), (j==2)?'\n':' '); // Warning here!!
    } 

    for (int j = 0; j < 3; j++) {
      printf("%d%c", *(*(arr5+1)+j), (j==2)?'\n':' ');
      //               ^ 
    }
return 0;
}

输出

-13412 -13400 -13388  UB UB UB
4 5 6                 OK OK OK