void foo(double **A, double **B) {
//....
}
int main() {
double **A;
double B[10][10];
int i, j;
A = (double **)malloc(sizeof(double*) * 10);
for (i = 0; i < 10; i++) {
*(A+i) = (double*)malloc(sizeof(double) * 10);
for (j = 0; j < 10; j++) {
*(*(A+i)+j) = i * j;
}
}
foo(A, B);
return 0;
}
这给了我一个警告
warning: incompatible pointer types passing 'double [10][10]' to parameter of type 'double **'
[-Wincompatible-pointer-types]
根据我的理解,B保存一个指向double类型指针的指针。我不是用A和B做同样的事情。为什么我只收到B的警告?
答案 0 :(得分:2)
B
是一个10 double
的数组数组,与指向double
数组的指针数组的类型非常不同。将foo
的原型更改为:
void foo(double **A, double (*B)[10])
同样以这种方式简化main
中的代码:
int main() {
double **A;
double B[10][10];
int i, j;
A = malloc(10 * sizeof(*A));
for (i = 0; i < 10; i++) {
A[i] = malloc(10 * sizeof(*A[i]));
for (j = 0; j < 10; j++) {
A[i][j] = i * j;
}
}
foo(A, B);
return 0;
}
答案 1 :(得分:1)
尝试void foo(double **A, double B[10][10])
然后传递foo(A, B)
答案 2 :(得分:1)
从语法角度将指针传递给数组和指针指向之间的主要区别并不难理解。当您将指针传递给数组array[x][y]
或(*array)[y]
时,您可以将参数指定为:
somefunc (type array[][y])
或
somefunc (type (*array)[y])
要带走的规则 - 在将指针传递给数组时,必须始终传递所涉及的列数。
另一方面,当将指针指向类型时,只需传递指针即可。 e.g:
somefunc (type **array)
“为什么?”的主要区别在于如何将信息存储在内存中。以int array[x][y]
为例。在那里,你有x * y
个整数存储在一个连续的内存块中。 x
和y
为该顺序块中的整数提供直接索引。 (x
数组中的任何位置,每个数组都包含y
个值。
另一方面,使用int **array
,您有一个指针指针 - 意味着您的array[x]
值标识指向另一个指针的点,该指针包含y
数组的起始地址值。不要求array[0]
,array[1]
,...
标识的任何单独指针都以任何顺序方式存储。
采用以下示例。您有array
(典型的array[x][y]
或2D数组,因为它经常被引用)和arraydp
数组的指向指针的类型 (典型的双指针)。该示例显示了必须处理每种方式的不同方式。
游戏中的调整是一个函数只能返回一个值(一个指针),所以要返回一个array[x][y]
的引用,它必须作为双指针返回并适当地重新设置。
#include <stdio.h>
#include <stdlib.h>
#define MAX 5
/* function prototypes */
int **alloc_fill (size_t n);
int **alloc_fill_dp (size_t n);
void prn_array (int (*a)[MAX], size_t nrow);
void prn_array_dp (int **a, size_t nrow, size_t ncol);
int main (int argc, char **argv) {
int (*array)[MAX] = { NULL }; /* pointer to array of MAX ints */
int **arraydp = NULL; /* pointer to pointer to int */
size_t i, n;
n = argc > 1 ? atoi(argv[1]) : 5; /* set number of rows */
/* fill 'n' pointer to array[MAX] */
array = (int (*)[MAX])alloc_fill (n);
/* fill 'n' pointer to pointer to int */
arraydp = alloc_fill_dp (n);
if (!array || !arraydp ) { /* validate both allocated */
fprintf (stderr, "error: alloc_fill failed.\n");
return 1;
}
printf ("\n elements of '%zu' arrays:\n\n", n);
prn_array (array, n);
printf ("\n elements of '%zu' arrays:\n\n", n);
prn_array_dp (arraydp, n, MAX);
free (array); /* single call to free for 'array' */
for (i = 0; i < n; i++) /* free each pointer, then arraydp */
free (arraydp[i]);
free (arraydp);
return 0;
}
/* allocate/fill 'n' pointer to array of MAX int */
int **alloc_fill (size_t n)
{
int (*a)[MAX] = { NULL };
size_t i, j;
if (!(a = calloc (n, sizeof **a * MAX))) {
fprintf (stderr, "error: virtual memory exhausted.\n");
return NULL;
}
for (i = 0; i < n; i++)
for (j = 0; j < MAX; j++)
a[i][j] = (i + 1) * (j + 1);
return (int **)a;
}
/* allocate/fill 'n' pointer to pointer to type int */
int **alloc_fill_dp (size_t n)
{
int **a = NULL;
size_t i, j;
/* allocate 'n' pointers */
if (!(a = calloc (n, sizeof *a))) {
fprintf (stderr, "error: virtual memory exhausted.\n");
return NULL;
}
for (i = 0; i < n; i++) {
/* allocate MAX ints */
if (!(a[i] = calloc (MAX, sizeof **a))) {
fprintf (stderr, "error: virtual memory exhausted.\n");
return NULL;
}
for (j = 0; j < MAX; j++)
a[i][j] = (i + 1) * (j + 1);
}
return a;
}
/* print function for 'nrow' pointers
* to array of 'MAX' ints
*/
void prn_array (int (*a)[MAX], size_t nrow)
{
size_t i,j;
for (i = 0; i < nrow; i++) {
for (j = 0; j < MAX; j++)
printf (" %4d", a[i][j]);
// putchar ('\n');
putchar ('\n'), putchar ('\n');
}
}
/* printf function for 'nrow' pointers
* to pointer to 'ncol' ints
*/
void prn_array_dp (int **a, size_t nrow, size_t ncol)
{
size_t i,j;
for (i = 0; i < nrow; i++) {
for (j = 0; j < ncol; j++)
printf (" %4d", a[i][j]);
// putchar ('\n');
putchar ('\n'), putchar ('\n');
}
}
<强>输出强>
$ ./bin/array_ptr_to_array
elements of '5' arrays:
1 2 3 4 5
2 4 6 8 10
3 6 9 12 15
4 8 12 16 20
5 10 15 20 25
elements of '5' arrays:
1 2 3 4 5
2 4 6 8 10
3 6 9 12 15
4 8 12 16 20
5 10 15 20 25
内存中存储的差异
在记忆中,橡胶与道路相遇。我看下面,您有gdb
和array
的内存布局的调试器(arraydp
)描述。注意array
所有值都是顺序的。但是,对于arraydp
,第一个5
值是指针地址,指向构成5 int
值的各个arraydp
数组。然后,如果您检查arraydp[0-4]
的指针地址,则可以为每个单独的值编制索引:
array
:
(gdb) x/25d array
0x603010: 1 2 3 4
0x603020: 5 2 4 6
0x603030: 8 10 3 6
0x603040: 9 12 15 4
0x603050: 8 12 16 20
0x603060: 5 10 15 20
0x603070: 25
内存中的 arraydp
:
(gdb) x/49d arraydp
0x603080: 6303920 0 6303952 0
0x603090: 6303984 0 6304016 0
0x6030a0: 6304048 0 33 0
0x6030b0: 1 2 3 4
0x6030c0: 5 0 33 0
0x6030d0: 2 4 6 8
0x6030e0: 10 0 33 0
0x6030f0: 3 6 9 12
0x603100: 15 0 33 0
0x603110: 4 8 12 16
0x603120: 20 0 33 0
0x603130: 5 10 15 20
0x603140: 25
(gdb) x/5d 6303920
0x6030b0: 1 2 3 4
0x6030c0: 5
(gdb) x/5d 6303952
0x6030d0: 2 4 6 8
0x6030e0: 10
(gdb) x/5d 6303984
0x6030f0: 3 6 9 12
0x603100: 15
(gdb) x/5d 6304016
0x603110: 4 8 12 16
0x603120: 20
(gdb) x/5d 6304048
0x603130: 5 10 15 20
0x603140: 25
从编程的角度来看,差异可能看起来微妙,但从语法角度来看,它们是至关重要的。仔细看看,如果您有其他问题,请告诉我。