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做这个警告?
最佳答案
从语法的角度来看,将指针传递给数组和指针传递给指针之间的主要区别并不太难理解。将指针传递到数组时,可以将参数指定为:
somefunc (type array[][y])
或
somefunc (type (*array)[y])
要去掉的规则——当向数组传递指针时,必须始终传递所涉及的列数。
另一方面,当将指针传递给类型指针时,只需要传递指针。例如。:
somefunc (type **array)
“为什么?”与信息如何存储在内存中有关。以
array[x][y]
为例。这里有(*array)[y]
整数存储在一个连续的内存块中。int array[x][y]
和x * y
为该序列块中的整数提供直接索引。(在每个包含x
值的y
数组中的任何位置)。另一方面,使用
x
,您有一个指向指针的指针——这意味着您的y
值标识指向另一个指针的指针,该指针包含int **array
值数组的起始地址不要求以任何顺序存储由array[x]
、y
、array[0]
标识的任何单独指针。以下面的例子为例。您拥有
array[1]
(通常所指的典型...
或2D数组)和array
指向类型指针的数组(典型的双指针)。该示例显示了处理每个传递的不同方式。游戏中的调整是,一个函数只能返回一个值(一个指针),因此要返回对
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
内存存储差异
在记忆中,这里是橡胶与道路相接的地方。如果您查看下面的内容,您将得到
arraydp
和array[x][y]
内存布局的调试器(gdb
)描述。注意array
所有值都是连续的。但是,对于arraydp
,第一个array
值是指向组成arraydp
值的每个5
数组的指针地址。如果随后检查指针地址中的5 int
,则可以索引每个单独的值:arraydp
内存中:(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[0-4]
内存中:(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
从编程的角度来看,这些差异似乎很微妙,但从语法的角度来看,它们是至关重要的。再看一遍,如果你还有问题,请告诉我。
关于c - 将指针传递给函数指针,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34803447/