【问题标题】:Why I cannot use int arr[2][2] as a parameter?为什么我不能使用 int arr[2][2] 作为参数?
【发布时间】:2020-01-26 08:57:04
【问题描述】:
void setArr(int x[2][2], int a, int b)
{
    for (int i = 0; i < a; i++)
        for (int j = 0; j < b; j++)
            x[i][j] = 0;
}
int main(void)
{
    int *arr[2];
    for (int i = 0; i < 2; i++) {
        arr[i] = malloc(sizeof(int) * 2);
    }
    setArr(arr, 2, 2);
}

我知道这段代码不起作用,但我不知道它背后的原因。任何人都可以向我解释为什么,在这种情况下,我不能使用 x[2][2] 作为接收 arr 的参数。 谢谢

我将代码放入可视化工具中,setArr 函数将 arr 的元素设置为 NULL。我知道 NULL 在 C 中是 0。但我无法连接为什么以及如何将 arr 的元素设置为 NULL。

【问题讨论】:

  • 这是一本很好的读物——希望对你有所帮助——geeksforgeeks.org/pass-2d-array-parameter-c
  • 因为int *arr[2]; 声明了一个指针数组,而void setArr(int x[2][2], ...) 需要一个指向int [2 ]。你想要void setArr(int **x, int a, int b)
  • @DavidC.Rankin 不,他们可能不想要int**,因为他们需要一个二维数组。
  • @Lundin - 这是函数设置要采用的,但不是 main() 中声明的。一个或另一个必须改变。假设int *arr[2]; 的main() 中的声明和后续分配是有意的,那么参数必须更改为int **x。如果上面的main() 是错误的,而预期是int arr[2][2];,那么循环和分配就没有意义了。你怎么知道哪个是正确的?

标签: c


【解决方案1】:

x[2][2] 只是一个变量的声明;无需在函数的输入中声明 var;您必须先声明它并使用它的地址:

void setArr(int** x, int a, int b)

【讨论】:

    【解决方案2】:

    函数声明 void setArr(int x[2][2], int a, int b) 将 setArr 声明为一个函数,该函数将一个包含 2 个数组的数组作为第一个参数,每个数组包含 2 个整数。而在main 中,您将arr(您传递给setArr 的变量)声明为int *arr[2],即作为指向2 个整数数组的指针。

    解决方案是更改main 中的代码,例如将arr 声明为int arr[2][2] 并删除for 循环,或者更改setArr 以便它接受一个指向两个数组的指针整数void setArr(int *x[2], int a, int b).

    我不确定后者是否会导致任何问题(gcc -Wall 编译时没有警告),但需要注意的一点是在将 arr 声明为指向大小为 2 的数组的指针时内存布局的差异或将其声明为由 2 个大小为 2 的数组组成的数组。编译和执行以下代码应该可以看出区别:

        int main(void) {
            int *arr[2];
            for (int i = 0; i < 2; i++) {
                arr[i] = malloc(sizeof(int) * 2); 
            }   
            printf("The address of arr[0] is %p\n", &arr[0]);
            printf("The address of arr[1] is %p\n\n", &arr[1]);
            printf("The address of arr[0][0] is %p\n", &arr[0][0]);
            printf("The address of arr[0][1] is %p\n", &arr[0][1]);
            printf("The address of arr[1][0] is %p\n", &arr[1][0]);
            printf("The address of arr[1][1] is %p\n\n", &arr[1][1]);
    
            int arr2[2][2]; 
            printf("The address of arr2[0] is %p\n", &arr2[0]);
            printf("The address of arr2[1] is %p\n\n", &arr2[1]);
            printf("The address of arr2[0][0] is %p\n", &arr2[0][0]);
            printf("The address of arr2[0][1] is %p\n", &arr2[0][1]);
            printf("The address of arr2[1][0] is %p\n", &arr2[1][0]);
            printf("The address of arr2[1][1] is %p\n", &arr2[1][1]);
    
            // setArr(arr, 2, 2); 
    }
    

    在我的机器上运行一次可执行文件,我得到以下信息:

    The address of arr[0] is 0x7ffe43d226b0
    The address of arr[1] is 0x7ffe43d226b8
    
    The address of arr[0][0] is 0xb62010
    The address of arr[0][1] is 0xb62014
    The address of arr[1][0] is 0xb62030
    The address of arr[1][1] is 0xb62034
    
    The address of arr2[0] is 0x7ffe43d226c0
    The address of arr2[1] is 0x7ffe43d226c8
    
    The address of arr2[0][0] is 0x7ffe43d226c0
    The address of arr2[0][1] is 0x7ffe43d226c4
    The address of arr2[1][0] is 0x7ffe43d226c8
    The address of arr2[1][1] is 0x7ffe43d226cc
    

    可以看到,当声明arr为数组指针时,两个整数的两个数组不是contiguous,而当声明为数组数组时,它们是。此外,当将其声明为数组数组时,无需动态分配内存(例如,使用malloc)。

    【讨论】:

      【解决方案3】:

      谁能解释一下为什么,在这种情况下,我不能使用 x[2][2] 作为参数来接收 arr。

      因为您使用的是截然不同的类型。 int *arr[2]; 是一个由 2 个 int* 组成的数组,每个都分配给一个已分配的内存块。如果您愿意,那是一个查找表或“锯齿状数组”,而不是一个正确的二维数组。详情请见Correctly allocating multi-dimensional arrays。

      分配二维数组的正确代码如下:

      #include <stdlib.h>
      
      void setArr(int a, int b, int x[a][b])
      {
          for (int i = 0; i < a; i++)
              for (int j = 0; j < b; j++)
                  x[i][j] = 0;
      }
      
      int main(void)
      {
          int (*arr)[2] = malloc(sizeof(int[2][2])); 
          setArr(2, 2, arr);
          free(arr);
      }
      

      这里的arr in main 是指向int[2][2] 的第一个元素的指针。该二维数组的第一个元素是int[2],指向这样一个元素的指针是int(*)[2]。

      【讨论】:

        猜你喜欢
        • 2020-07-03
        • 2017-11-06
        • 2014-07-22
        • 1970-01-01
        • 2021-02-17
        • 2011-11-04
        • 1970-01-01
        • 2021-02-03
        相关资源
        最近更新 更多