如果静态声明而不提及函数头中的大小,为什么不将矩阵传递给函数呢?

时间:2016-01-23 17:02:03

标签: c arrays pointers multidimensional-array

我正在尝试使下面的代码工作,但据我所知,有两个选项将矩阵传递给函数:

  1. 在标题中指定矩阵的大小,如下所示:grunt
  2. 动态地分配它而不是void f(int v[100][100], int n)
  3. 为什么它不会像下面的代码一样工作?不是说[100] [100]与动态分配相同吗?不是[i] [j]和*(*(a + i)+ j)相同吗?

    int a[100][100]

2 个答案:

答案 0 :(得分:4)

数组衰减到指针,这就是为什么你可以写:

void foo(int *p);
void foo(int p[]); // equivalent (use the above form)

int v[100];
foo(v);

对于多维数组,只有第一个数组"衰减"。因此矩阵(将其视为数组数组)衰减到指向数组:

void foo(int (*p)[100]);
void foo(int p[][100]);   // equivalent (use the above form)

int m[100][100];
foo(m);

原因与内存布局有关:

一维数组:

char v[3] = {'a', 'b', 'c'};

| a | b | c |

正如您所看到的那样,通过char *指针访问它是微不足道的。

二维数组:

char m[2][3] = {{'a', 'b', 'c'}, {'d', 'e', 'f'}};

| a | b | c | d | e | f |
|           |           |

上述数组无法衰减为char **char **会有这种布局:

| addr | addr | addr | ...

在内存中会有指向char存储的指针。

因此m可以衰减到指向char char (*p)[3]的数组3的指针。必须知道3,因为它给出了引用对象的大小,这绝对需要知道:取消引用和指针算术工作(例如p++

char (*p)[3]:

| a | b | c | d | e | f |
|           |           |

所以第一个p元素p[0]char[3]数组{a,b,c}p[1]char[3]数组{d,e,f}

注意我使用char更好地将元素显示为字符。但那些不是C字符串,因为它们不是NULL终止的。用int代替,如果它让你更舒服。

答案 1 :(得分:1)

当一个函数参数被声明为具有数组类型时,它被调整为指向数组元素类型的指针。

因此,当一个数组作为参数传递给函数或在表达式中使用时,它会被隐式转换为指向其第一个元素的指针。

所以如果你有一个数组

int a[100][100];

并使用其名称作为某个函数的参数

some_function( a, 100 );

然后将其转换为int ( * )[100]类型。

相应地,函数参数必须以下列方式之一声明

void f( int a[100][100], size_t n );

void f( int a[][100], size_t n );

void f( int ( *a )[100], size_t n );

所有这些声明都是等效的,并声明相同的一个函数。

您可以动态定义数组,例如

int ( *a )[100] = malloc( 100 * 100 * sizeof( int ) );

并按照上面显示的方式调用该函数

some_function( a, 100 );

但是,如果您将动态定义一维数组数组,例如

int **a = malloc( 100 * sizeof( int *  ) );

for ( size_t i = 0; i < 100; i++ ) a[i] = malloc( 100 * sizeof( int ) );

然后您可以看到变量a的类型为int **。它与int ( *a )[100]不同。因此该函数应该声明为

void f( int *a[100], size_t n );

void f( int *a[], size_t n );

void f( int **a, size_t n );

如您所见,显示了两个不同的数组和指针声明,以及相应的两个不同的函数声明,它们取决于数组或指针的类型。