传递一维数组,二维数组和指针数组

时间:2018-07-04 08:15:20

标签: c arrays pointers

要将一维数组传递给函数,我们可以这样做:

#include <stdio.h>
#include <stdlib.h>

void func(int *arr, int n)
{
    // code here

}

int main()
{
    int arr[] = {......};                   // declare array
    int n = sizeof(arr)/sizeof(arr[0]);
    func(arr);                              // calling function func

    return 0;
}

要将2D数组传递给函数,我们可以这样做:

#include <stdio.h>
#include <stdlib.h>

void func(int arr[][2])
{
    // code here
    }

int main()
{
    int arr[3][2];  // declare 2D array
    func(arr);      // calling function func

    return 0;
}

那么在将指针数组传递给函数时,我们可以做这样的事情吗?

#include <stdio.h>
#include <stdlib.h>

void func(int **arr, int n)
{
    // code here

}

int main()
{
    int *arr[] = {......};                // declare array of pointers
    int n = sizeof(arr)/sizeof(arr[0]);
    func(arr, n);                           // calling function func

    return 0;
}

老实说,我对指针和数组感到困惑。我花了很长时间弄清楚如何传递2D阵列。我尝试搜索其他类似的问题,但无济于事。请帮助我:将指针数组传递给函数。此外,我能消除混乱的任何链接也将不胜感激。

3 个答案:

答案 0 :(得分:5)

在最后一个示例中,您有一个指针数组

是的,这可以工作,例如检查以下玩具示例:

#include <stdio.h>
#include <stdlib.h>

void func(int **arr, int n) {

    // print equal to arr[0][1] 
    printf("%d %d\n", n, *arr[1]);
}

int main(void) {
    int a = 1, b = 2, c = 3;

    // set the points of a, b, and c, to arr[0][0..2];
    int *arr[] = {&a, &b, &c};
    int n = sizeof(arr)/sizeof(arr[0]);
    printf("%d %d\n", n, *arr[1]);

    func(arr, n);

    return 0;
}

输出:

3 2
3 2

答案 1 :(得分:3)

  

老实说,我对指针和数组感到困惑。我花了很长时间才弄清楚如何传递2D数组。

这种混乱非常普遍。这源于您在C语言中无法传递数组的事实,但是该语言允许使用一种语法,使其看起来像您可能的样子。

因此,由于您无法将数组传递给函数,因此您要做的是将指针传递给第一个数组元素以及(如果需要)数组的大小。在函数内部,可以使用该指针访问数组,并且语法看起来像是实际数组一样。这还需要一些解释:

  • []是索引运算符,其工作原理是将索引添加到给定的指针,然后取消对结果指针的引用。因此,编写a[5]*(a+5)完全相同。
  • 即使a是实际数组(而不是指针),这也可以使用,因为在大多数情况下,数组的求值结果是指向第一个元素的指针(存在类似sizeof运算符)。

为了使事情变得更复杂,C允许声明看起来像在使用数组的函数,例如你可以这样写:

void foo(int bar[]);

C标准中有一条规则规定函数参数类型必须进行“ 类型调整”:数组类型的任何参数都将自动调整为相应的指针类型。因此,上面的功能实际上与

相同
void foo(int *bar);

因此,最好不要传递数组(我什至建议不要在函数参数中使用数组语法,但这有待商))-您总是传递指针。


借助这些知识,您可以轻松地为所有案例构建正确的示例:

(1)“普通”数组

void foo(int bar[], size_t n); // with type adjustment
void foo(int *bar, size_t n);  // what it really means

// call like
int a[5];
foo(a, 5);

(2) 2D阵列

2D数组是数组的数组,因此它的第一个元素本身就是数组->您将指针传递给数组

void foo(int bar[][10], int n);  // with type adjustment, 2d array of n x 10
void foo(int (*bar)[10], int n); // what it really means

// call like:
int a[5][10];
foo(a, 5);

(3)指针数组

通常使用指针数组代替2d数组-由于元素只是指针,它们可以指向单个值或不同长度的数组,但是缺点是您没有完整的数组数据作为内存中的单个块,就像真正的2d数组那样。由于这只是一个指针数组,因此看起来非常像正在使用的“普通”数组:

void foo(int *bar[], int n); // with type adjustment
void foo(int **bar, int n);  // what it really means

// call like:
int *a[5];
foo(a, 5);

最后的注释:您经常会在C语言中读到“作为指针衰减”的数组。这不是官方用语,而是非常普遍的。如果在大多数情况下(例如,将其传递给函数时)将数组标识符评估为指针的规则与函数参数的类型调整规则结合在一起,则结果是您编写了数组语法到处都有,但要获得指针,这就是“衰减”的含义。

答案 2 :(得分:1)

一维数组,二维数组,X-D数组和指针数组之间实际上没有区别。它们全都是随之而来的存储区域。

一维数组:

int arr[8];
int *addr = arr;

| arr[0] | ...*6... | arr[7] |
^                   ^
|                   |
addr                 addr+7

二维数组:

int arr[4][2]
int *addr = arr[0];

| arr[0][0] | ...*6... | arr[3][1] |
^                      ^
|                      |
addr                   addr+7 

3-D数组:

int arr[2][2][2];
int *addr = arr[0][0];

| arr[0][0][0] | ...*6... | arr[1][1][1] |
^                         ^
|                         |
addr                      addr+7

指针数组:

typedef pointer int*;
...

int a0[8] = {0, 1, 2, 3, 4, 5, 6, 7};
int a1[7] = {0, 1, 2, 3, 4, 5, 6};
...
int a7[1] = {0};

pointer arr[8] = {a0, a1, a2, a3, a4, a5, a6, a7};
pointer *addr = arr;

| arr[0] = a1 | ...*6... | arr[7] = a7 |
^                        ^
|                        |
addr                     addr+7

定义X-D数组可以通过以下方式实现:

typedef data_type int;

typedef struct X-Array
{
    int d1;
    int d2;
    ...
    int dx;
    data_type *data;
} X-Array;

X-Array *create_X_Array(int d1, int d1, ..., int dx)
{
    X-Array *arr;
    if ((arr = malloc(sizeof(X-Array))) == NULL)
        return NULL;

    if ((arr->data = malloc(sizeof(data_type * d1 * d2 * ... * dx))) == NULL)
    {
        free(arr);
        return NULL;
    }

    arr->d1 = d1;
    arr->d2 = d2;
    ...
    arr->dx = dx;

    return arr;
}