【问题标题】:Difference in function parameter: double pointer VS 2D array [duplicate]函数参数的差异:双指针VS 2D数组[重复]
【发布时间】:2019-09-02 11:57:04
【问题描述】:

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

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

但是当这些被用作函数参数时呢?

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

除了提示func2中值的个数外,有没有功能上的区别?

【问题讨论】:

  • 您是否尝试过同时使用这两种方法,看看会发生什么?

标签: c arrays function pointers


【解决方案1】:

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

double **arr 不是数组,它只是一个指向double 的指针。你有 没有更多信息。您无法事先知道 arr 是一个双精度数组。因此,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,然后跳过第二个数组的两个 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

【讨论】:

  • 不会将 const_arr 传递给 func2 和 func1 在功能上相似吗?
  • 不,不会。从 GCC 警告中可以看出,您不能这样做。这会导致func1() 段错误非常严重。
  • 你的意思是 func2 会崩溃?
  • 不,func1(const_arr) 崩溃。看我的回答。阅读警告。
  • 你不能打电话给func1(const_arr),你也不能打电话给func2(double_ptr)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-07-25
  • 2015-07-01
  • 2014-01-04
  • 1970-01-01
  • 2012-11-17
  • 2015-03-09
相关资源
最近更新 更多