c - 功能参数差异 : double pointer VS 2D array

标签 c arrays function pointers

<分区>

请理解,在声明的情况下,以下两行是不等价的(在分配方面)

double ** v1;
double v2[3][3];

但是当它们用作函数参数时呢?

void func1(double** v1)
void func2(double v2[3][3])

除了关于 func2 中值数量的提示外,是否存在功能差异?

最佳答案

严格来说,double **arrdouble arr[3][3] 是两种完全不同的类型。

double **arr 不是数组,它只是指向 double 的指针。你有 没有更多信息。您无法事先知道 arr 是 double 组的数组。所以执行 arr[1][2] 将意味着“跳过第一个 double 指针取消引用第二个指针作为采用第三个元素(索引 2)的数组。

因此,x = arr[1][2] 可以翻译为以下伪代码:

tmp = memory[<arr_address> + sizeof(double *)]
x = memory[<tmp_address> + 2*sizeof(double)]

double arr[3][3],反之,是一个常量数组,可以做更多的假设。它保证在内存中是连续的并且执行 arr[1][2] 意味着“跳过 3 double 的第一个数组,然后 < strong>跳过第二个数组的两个 double 并查看第三个(索引 2)。

因此,x = arr[1][2] 可以翻译为以下伪代码:

x = memory[<arr_address> + (3 + 2)*sizeof(double)]

作为实际示例,请考虑以下程序:

int func1(int** v1) {
    return v1[1][2];
}

int func2(int v2[3][3]) {
    return v2[1][2];
}

int main(void) {
    int const_arr[3][3]; // Values are not important.
    int **double_ptr;    // We don't really run this code!

    func1(const_arr);
    func2(double_ptr);
}

编译时,它会给出以下(非常相关的)警告:

arrayparam.c: In function ‘main’:
arrayparam.c:13:8: warning: passing argument 1 of ‘func1’ from incompatible pointer type [-Wincompatible-pointer-types]
  func1(const_arr);
        ^~~~~~~~~
arrayparam.c:1:5: note: expected ‘int **’ but argument is of type ‘int (*)[3]’
 int func1(int** v1) {
     ^~~~~
arrayparam.c:14:8: warning: passing argument 1 of ‘func2’ from incompatible pointer type [-Wincompatible-pointer-types]
  func2(double_ptr);
        ^~~~~~~~~~
arrayparam.c:5:5: note: expected ‘int (*)[3]’ but argument is of type ‘int **’
 int func2(int v2[3][3]) {

从生成的程序集可以非常清楚的看出,这两个函数做了完全不同的事情,这段汇编代码真的和我上面写的伪代码一样:

func1():

664:   48 89 7d f8             mov    QWORD PTR [rbp-0x8],rdi
668:   48 8b 45 f8             mov    rax,QWORD PTR [rbp-0x8] ; load the array
66c:   48 83 c0 08             add    rax,0x8                 ; go 1*8 = 8 bytes forward (sizeof(int*))
670:   48 8b 00                mov    rax,QWORD PTR [rax]     ; dereference that pointer
673:   8b 40 08                mov    eax,DWORD PTR [rax+0x8] ; go 2*4 = 8 bytes forward (2*sizeof(int)) and take the value there

func2():

67c:   48 89 7d f8             mov    QWORD PTR [rbp-0x8],rdi
680:   48 8b 45 f8             mov    rax,QWORD PTR [rbp-0x8] ; load the array
684:   48 83 c0 0c             add    rax,0xc                 ; go 3*4 = 12 bytes forward
688:   8b 40 08                mov    eax,DWORD PTR [rax+0x8] ; go another 2*4 = 8 bytes forward and take the value there

关于c - 功能参数差异 : double pointer VS 2D array,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57756564/

相关文章:

c - 如果程序将退出,使用临时 realloc 变量有什么意义?

编译涉及 'sys_mount'调用的模块

arrays - VBA中的列表和数组

c++ - 是否支持从 unique_ptr 到原始指针的隐式转换?

javascript - 确定javascript函数中的调用div

c - 如何在C中对字符串数组与整数数组并行排序?没有结构体?

python - 在二维数组中添加列 (Python)

c++ - _beginthreadex 静态成员函数

python - 调用此内存函数会引发 TypeError : unhashable type: 'dict'

c - C语言十进制转二进制