函数参数的区别:双指针VS二维数组[重复]

问题描述 投票:0回答:1

请理解,在声明的情况下,以下两行并不等效(就分配而言)

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

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

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

除了

func2
中关于值的数量的提示之外,还有功能上的区别吗?

c arrays function pointers
1个回答
3
投票

严格来说,

double **arr
double 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

	
© www.soinside.com 2019 - 2024. All rights reserved.