将2D数组传递给c++函数

时间:2022-05-31 21:37:32

I have a function which I want to take, as a parameter, a 2D array of variable size.

我有一个函数,我想把它作为一个参数,一个可变大小的二维数组。

So far I have this:

到目前为止,我有:

void myFunction(double** myArray){
     myArray[x][y] = 5;
     etc...
}

And I have declared an array elsewhere in my code:

我在代码中已经声明了一个数组:

double anArray[10][10];

However, calling myFunction(anArray) gives me an error.

但是,调用myFunction(anArray)会给我一个错误。

I do not want to copy the array when I pass it in. Any changes made in myFunction should alter the state of anArray. If I understand correctly, I only want to pass in as an argument a pointer to a 2D array. The function needs to accept arrays of different sizes also. So for example, [10][10] and [5][5]. How can I do this?

我不想在传入数组时复制它。myFunction中的任何更改都应该改变数组的状态。如果我理解正确,我只想将指向2D数组的指针作为参数传入。函数还需要接受不同大小的数组。比如[10][10]和[5][5]。我该怎么做呢?

11 个解决方案

#1


318  

There are three ways to pass a 2D array to a function:

将二维数组传递给函数有三种方式:

  1. The parameter is a 2D array

    参数是一个2D数组

    int array[10][10];
    void passFunc(int a[][10])
    {
        // ...
    }
    passFunc(array);
    
  2. The parameter is an array containing pointers

    参数是一个包含指针的数组

    int *array[10];
    for(int i = 0; i < 10; i++)
        array[i] = new int[10];
    void passFunc(int *a[10]) //Array containing pointers
    {
        // ...
    }
    passFunc(array);
    
  3. The parameter is a pointer to a pointer

    参数是指向指针的指针

    int **array;
    array = new int *[10];
    for(int i = 0; i <10; i++)
        array[i] = new int[10];
    void passFunc(int **a)
    {
        // ...
    }
    passFunc(array);
    

#2


123  

Fixed Size

1. Pass by reference

1。通过引用传递

template <size_t rows, size_t cols>
void process_2d_array_template(int (&array)[rows][cols])
{
    std::cout << __func__ << std::endl;
    for (size_t i = 0; i < rows; ++i)
    {
        std::cout << i << ": ";
        for (size_t j = 0; j < cols; ++j)
            std::cout << array[i][j] << '\t';
        std::cout << std::endl;
    }
}

In C++ passing the array by reference without losing the dimension information is probably the safest, since one needn't worry about the caller passing an incorrect dimension (compiler flags when mismatching). However, this isn't possible with dynamic (freestore) arrays; it works for automatic (usually stack-living) arrays only i.e. the dimensionality should be known at compile time.

在c++中,通过引用传递数组而不丢失维度信息可能是最安全的,因为不必担心调用者传递不正确的维度(当不匹配时,编译器标记)。然而,对于动态(独立)数组来说,这是不可能的;它只适用于自动(通常是堆栈)数组,也就是说,在编译时应该知道维度。

2. Pass by pointer

2。通过指针

void process_2d_array_pointer(int (*array)[5][10])
{
    std::cout << __func__ << std::endl;
    for (size_t i = 0; i < 5; ++i)
    {
        std::cout << i << ": ";
        for (size_t j = 0; j < 10; ++j)
            std::cout << (*array)[i][j] << '\t';
        std::cout << std::endl;
    }    
}

The C equivalent of the previous method is passing the array by pointer. This should not be confused with passing by the array's decayed pointer type (3), which is the common, popular method, albeit less safe than this one but more flexible. Like (1), use this method when all the dimensions of the array is fixed and known at compile-time. Note that when calling the function the array's address should be passed process_2d_array_pointer(&a) and not the address of the first element by decay process_2d_array_pointer(a).

前一个方法的C等价于通过指针传递数组。这不应该与传递数组的衰减指针类型(3)混淆,后者是常见的、流行的方法,虽然不如这个方法安全,但更灵活。与(1)类似,当数组的所有维数都固定且在编译时已知时,使用此方法。注意,在调用函数时,数组的地址应该通过process_2d_array_pointer()传递,而不是通过衰变process_2d_array_pointer(a)传递第一个元素的地址。

Variable Size

These are inherited from C but are less safe, the compiler has no way of checking, guaranteeing that the caller is passing the required dimensions. The function only banks on what the caller passes in as the dimension(s). These are more flexible than the above ones since arrays of different lengths can be passed to them invariably.

这些是从C继承而来的,但是安全性较差,编译器没有检查的方法,保证调用者正在传递所需的维度。该函数只存储调用者作为维度传入的内容。由于不同长度的数组总是可以传递给它们,所以它们比上面的数组更灵活。

It is to be remembered that there's no such thing as passing an array directly to a function in C [while in C++ they can be passed as a reference (1)]; (2) is passing a pointer to the array and not the array itself. Always passing an array as-is becomes a pointer-copy operation which is facilitated by array's nature of decaying into a pointer.

要记住,不存在直接将数组传递给C中的函数的情况[而在c++中,数组可以作为引用(1)传递];(2)向数组而不是数组本身传递指针。始终按原样传递一个数组就变成了指针复制操作,这是由于数组的衰减特性所促成的。

3. Pass by (value) a pointer to the decayed type

3所示。传递(值)一个指向衰减类型的指针

// int array[][10] is just fancy notation for the same thing
void process_2d_array(int (*array)[10], size_t rows)
{
    std::cout << __func__ << std::endl;
    for (size_t i = 0; i < rows; ++i)
    {
        std::cout << i << ": ";
        for (size_t j = 0; j < 10; ++j)
            std::cout << array[i][j] << '\t';
        std::cout << std::endl;
    }
}

Although int array[][10] is allowed, I'd not recommend it over the above syntax since the above syntax makes it clear that the identifier array is a single pointer to an array of 10 integers, while this syntax looks like it's a 2D array but is the same pointer to an array of 10 integers. Here we know the number of elements in a single row (i.e. the column size, 10 here) but the number of rows is unknown and hence to be passed as an argument. In this case there's some safety since the compiler can flag when a pointer to an array with second dimension not equal to 10 is passed. The first dimension is the varying part and can be omitted. See here for the rationale on why only the first dimension is allowed to be omitted.

虽然int[]数组允许[10],我不建议在上述语法因为上面的语法很清楚,标识符数组是一个指针指向一个10的整数数组,而这种语法看起来是一个二维数组,但相同的10个整数指针指向一个数组。在这里,我们知道一行中的元素数量(即列大小,这里是10),但是行数是未知的,因此要作为参数传递。在这种情况下,有一些安全性,因为当传递到第二个维度不等于10的数组的指针时,编译器可以标记。第一个维度是变化的部分,可以省略。在这里可以看到为什么只允许第一个维度被省略。

4. Pass by pointer to a pointer

4所示。通过指针指向指针

// int *array[10] is just fancy notation for the same thing
void process_pointer_2_pointer(int **array, size_t rows, size_t cols)
{
    std::cout << __func__ << std::endl;
    for (size_t i = 0; i < rows; ++i)
    {
        std::cout << i << ": ";
        for (size_t j = 0; j < cols; ++j)
            std::cout << array[i][j] << '\t';
        std::cout << std::endl;
    }
}

Again there's an alternative syntax of int *array[10] which is the same as int **array. In this syntax the [10] is ignored as it decays into a pointer thereby becoming int **array. Perhaps it is just a cue to the caller that the passed array should have at least 10 columns, even then row count is required. In any case the compiler doesn't flag for any length/size violations (it only checks if the type passed is a pointer to pointer), hence requiring both row and column counts as parameter makes sense here.

同样,int *array[10]的另一种语法与int **array相同。在此语法中,当[10]衰减成指针时,将被忽略,从而成为int **数组。也许这只是给调用者一个提示,即所传递的数组应该至少有10列,即使需要行数。在任何情况下,编译器都不会标记任何长度/大小违规(它只检查传递的类型是否为指针的指针),因此这里需要行和列计数作为参数。

Note: (4) is the least safest option since it hardly has any type check and the most inconvenient. One cannot legitimately pass a 2D array to this function; C-FAQ condemns the usual workaround of doing int x[5][10]; process_pointer_2_pointer((int**)&x[0][0], 5, 10); as it may potentially lead to undefined behaviour due to array flattening. The right way of passing an array in this method brings us to the inconvenient part i.e. we need an additional (surrogate) array of pointers with each of its element pointing to the respective row of the actual, to-be-passed array; this surrogate is then passed to the function (see below); all this for getting the same job done as the above methods which are more safer, cleaner and perhaps faster.

注:(4)是最不安全的选项,因为它几乎没有任何类型检查,而且最不方便。不能合法地将2D数组传递给这个函数;C-FAQ谴责做int x[5][10]的常见做法;process_pointer_2_pointer((int * *)x[0][0],5、10);因为它可能导致由于阵列扁平化而导致的未定义行为。在此方法中传递数组的正确方式将我们带到不方便的部分,即我们需要一个额外的指针(代理)数组,其每个元素都指向实际要传递的数组的相应行;然后将该代理传递给函数(见下面);所有这些都是为了完成与上述方法相同的工作,这些方法更安全、更干净,而且可能更快。

Here's a driver program to test the above functions:

下面是一个测试上述功能的驱动程序:

#include <iostream>

// copy above functions here

int main()
{
    int a[5][10] = { { } };
    process_2d_array_template(a);
    process_2d_array_pointer(&a);    // <-- notice the unusual usage of addressof (&) operator on an array
    process_2d_array(a, 5);
    // works since a's first dimension decays into a pointer thereby becoming int (*)[10]

    int *b[5];  // surrogate
    for (size_t i = 0; i < 5; ++i)
    {
        b[i] = a[i];
    }
    // another popular way to define b: here the 2D arrays dims may be non-const, runtime var
    // int **b = new int*[5];
    // for (size_t i = 0; i < 5; ++i) b[i] = new int[10];
    process_pointer_2_pointer(b, 5, 10);
    // process_2d_array(b, 5);
    // doesn't work since b's first dimension decays into a pointer thereby becoming int**
}

#3


33  

A modification to shengy's first suggestion, you can use templates to make the function accept a multi-dimensional array variable (instead of storing an array of pointers that have to be managed and deleted):

对于shengy的第一个建议,您可以使用模板使函数接受一个多维数组变量(而不是存储一个必须管理和删除的指针数组):

template <size_t size_x, size_t size_y>
void func(double (&arr)[size_x][size_y])
{
    printf("%p\n", &arr);
}

int main()
{
    double a1[10][10];
    double a2[5][5];

    printf("%p\n%p\n\n", &a1, &a2);
    func(a1);
    func(a2);

    return 0;
}

The print statements are there to show that the arrays are getting passed by reference (by displaying the variables' addresses)

打印语句显示数组是通过引用(通过显示变量的地址)传递的

#4


19  

You can create a function template like this:

您可以创建这样的函数模板:

template<int R, int C>
void myFunction(double (&myArray)[R][C])
{
    myArray[x][y] = 5;
    etc...
}

Then you have both dimension sizes via R and C. A different function will be created for each array size, so if your function is large and you call it with a variety of different array sizes, this may be costly. You could use it as a wrapper over a function like this though:

然后通过R和c可以得到两个维度大小,每个数组大小都会创建一个不同的函数,所以如果函数很大,并且使用不同的数组大小调用它,这可能会很昂贵。您可以将它作为这样的函数的包装:

void myFunction(double * arr, int R, int C)
{
    arr[x * C + y] = 5;
    etc...
}

It treats the array as one dimensional, and uses arithmetic to figure out the offsets of the indexes. In this case, you would define the template like this:

它将数组视为一维,并使用算术方法计算索引的偏移量。在这种情况下,您可以这样定义模板:

template<int C, int R>
void myFunction(double (&myArray)[R][C])
{
    myFunction(*myArray, R, C);
}

#5


8  

anArray[10][10] is not a pointer to a pointer, it is a contiguous chunk of memory suitable for storing 100 values of type double, which compiler knows how to address because you specified the dimensions. You need to pass it to a function as an array. You can omit the size of the initial dimension, as follows:

anArray[10][10]不是指向指针的指针,而是适合存储100个类型为double的值的连续内存块,编译器知道如何寻址,因为您指定了维度。您需要将它作为数组传递给函数。可以忽略初始维度的大小,如下所示:

void f(double p[][10]) {
}

However, this will not let you pass arrays with the last dimension other than ten.

但是,这将不会让您传递带有除10以外的最后一个维度的数组。

The best solution in C++ is to use std::vector<std::vector<double> >: it is nearly as efficient, and significantly more convenient.

在c++中最好的解决方案是使用std::vector <:vector> >:它几乎是高效的,而且非常方便。

#6


6  

Single dimensional array decays to a pointer pointer pointing to the first element in the array. While a 2D array decays to a pointer pointing to first row. So, the function prototype should be -

单维数组衰减为指向数组中第一个元素的指针指针。当一个二维数组衰减到指向第一行的指针。因此,函数原型应该是-

void myFunction(double (*myArray) [10]);

I would prefer std::vector over raw arrays.

与原始数组相比,我更喜欢std::vector。

#7


6  

You can do something like this...

你可以做这样的事情…

#include<iostream>

using namespace std;

//for changing values in 2D array
void myFunc(double *a,int rows,int cols){
    for(int i=0;i<rows;i++){
        for(int j=0;j<cols;j++){
            *(a+ i*rows + j)+=10.0;
        }
    }
}

//for printing 2D array,similar to myFunc
void printArray(double *a,int rows,int cols){
    cout<<"Printing your array...\n";
    for(int i=0;i<rows;i++){
        for(int j=0;j<cols;j++){
            cout<<*(a+ i*rows + j)<<"  ";
        }
    cout<<"\n";
    }
}

int main(){
    //declare and initialize your array
    double a[2][2]={{1.5 , 2.5},{3.5 , 4.5}};

    //the 1st argument is the address of the first row i.e
    //the first 1D array
    //the 2nd argument is the no of rows of your array
    //the 3rd argument is the no of columns of your array
    myFunc(a[0],2,2);

    //same way as myFunc
    printArray(a[0],2,2);

    return 0;
}

Your output will be as follows...

您的输出将如下…

11.5  12.5
13.5  14.5

#8


6  

Surprised that no one mentioned this yet, but you can simply template on anything 2D supporting [][] semantics.

还没有人提到这一点,但您可以在任何支持[][][]语义的2D模板上简单地使用它。

template <typename TwoD>
void myFunction(TwoD& myArray){
     myArray[x][y] = 5;
     etc...
}

// call with
double anArray[10][10];
myFunction(anArray);

It works with any 2D "array-like" datastructure, such as std::vector<std::vector<T>>, or a user defined type to maximize code reuse.

它适用于任何2D“arraylike”数据结构,如std::vector <:vector> >,或用户定义的类型,以最大化代码重用。

#9


1  

One important thing for passing multidimensional arrays is:

传递多维数组的一个重要事项是:

  • First array dimension need not be specified.
  • 不需要指定第一个数组维度。
  • Second(any any further)dimension must be specified.
  • 第二(任何其他)维度必须指定。

1.When only second dimension is available globally (either as a macro or as a global constant)

1。当只有第二个维度是全局可用的(可以是宏,也可以是全局常量)

`const int N = 3;

`void print(int arr[][N], int m)
{
int i, j;
for (i = 0; i < m; i++)
  for (j = 0; j < N; j++)
    printf("%d ", arr[i][j]);
}`

int main()
{
int arr[][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
print(arr, 3);
return 0;
}`

2.Using a single pointer: In this method,we must typecast the 2D array when passing to function.

2。使用一个指针:在这个方法中,我们必须在传递给函数时进行2D数组的排版。

`void print(int *arr, int m, int n)
{
int i, j;
for (i = 0; i < m; i++)
  for (j = 0; j < n; j++)
    printf("%d ", *((arr+i*n) + j));
 }

`int main()
{
int arr[][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
int m = 3, n = 3;

// We can also use "print(&arr[0][0], m, n);"
print((int *)arr, m, n);
return 0;
}`

#10


0  

You can use template facility in C++ to do this. I did something like this :

您可以使用c++中的模板工具来实现这一点。我做了这样的事情:

template<typename T, size_t col>
T process(T a[][col], size_t row) {
...
}

the problem with this approach is that for every value of col which you provide, the a new function definition is instantiated using the template. so,

这种方法的问题是,对于您提供的每一个col值,使用模板实例化一个新的函数定义。所以,

int some_mat[3][3], another_mat[4,5];
process(some_mat, 3);
process(another_mat, 4);

instantiates the template twice to produce 2 function definitions (one where col = 3 and one where col = 5).

实例化模板两次以生成两个函数定义(一个在col = 3处,另一个在col = 5处)。

#11


-1  

We can use several ways to pass a 2D array to a function:

我们可以用几种方法将二维数组传递给函数:

  • Using single pointer we have to typecast the 2D array.

    使用单个指针,我们必须对2D数组进行排版。

    #include<bits/stdc++.h>
    using namespace std;
    
    
    void func(int *arr, int m, int n)
    {
        for (int i=0; i<m; i++)
        {
           for (int j=0; j<n; j++)
           {
              cout<<*((arr+i*n) + j)<<" ";
           }
           cout<<endl;
        }
    }
    
    int main()
    {
        int m = 3, n = 3;
        int arr[m][n] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
        func((int *)arr, m, n);
        return 0;
    }
    
  • Using double pointer In this way, we also typecast the 2d array

    用这种方式使用双指针,我们也排版二维数组

    #include<bits/stdc++.h>
    using namespace std;

   void func(int **arr, int row, int col)
   {
      for (int i=0; i<row; i++)
      {
         for(int j=0 ; j<col; j++)
         {
           cout<<arr[i][j]<<" ";
         }
         printf("\n");
      }
   }

  int main()
  {
     int row, colum;
     cin>>row>>colum;
     int** arr = new int*[row];

     for(int i=0; i<row; i++)
     {
        arr[i] = new int[colum];
     }

     for(int i=0; i<row; i++)
     {
         for(int j=0; j<colum; j++)
         {
            cin>>arr[i][j];
         }
     }
     func(arr, row, colum);

     return 0;
   }

#1


318  

There are three ways to pass a 2D array to a function:

将二维数组传递给函数有三种方式:

  1. The parameter is a 2D array

    参数是一个2D数组

    int array[10][10];
    void passFunc(int a[][10])
    {
        // ...
    }
    passFunc(array);
    
  2. The parameter is an array containing pointers

    参数是一个包含指针的数组

    int *array[10];
    for(int i = 0; i < 10; i++)
        array[i] = new int[10];
    void passFunc(int *a[10]) //Array containing pointers
    {
        // ...
    }
    passFunc(array);
    
  3. The parameter is a pointer to a pointer

    参数是指向指针的指针

    int **array;
    array = new int *[10];
    for(int i = 0; i <10; i++)
        array[i] = new int[10];
    void passFunc(int **a)
    {
        // ...
    }
    passFunc(array);
    

#2


123  

Fixed Size

1. Pass by reference

1。通过引用传递

template <size_t rows, size_t cols>
void process_2d_array_template(int (&array)[rows][cols])
{
    std::cout << __func__ << std::endl;
    for (size_t i = 0; i < rows; ++i)
    {
        std::cout << i << ": ";
        for (size_t j = 0; j < cols; ++j)
            std::cout << array[i][j] << '\t';
        std::cout << std::endl;
    }
}

In C++ passing the array by reference without losing the dimension information is probably the safest, since one needn't worry about the caller passing an incorrect dimension (compiler flags when mismatching). However, this isn't possible with dynamic (freestore) arrays; it works for automatic (usually stack-living) arrays only i.e. the dimensionality should be known at compile time.

在c++中,通过引用传递数组而不丢失维度信息可能是最安全的,因为不必担心调用者传递不正确的维度(当不匹配时,编译器标记)。然而,对于动态(独立)数组来说,这是不可能的;它只适用于自动(通常是堆栈)数组,也就是说,在编译时应该知道维度。

2. Pass by pointer

2。通过指针

void process_2d_array_pointer(int (*array)[5][10])
{
    std::cout << __func__ << std::endl;
    for (size_t i = 0; i < 5; ++i)
    {
        std::cout << i << ": ";
        for (size_t j = 0; j < 10; ++j)
            std::cout << (*array)[i][j] << '\t';
        std::cout << std::endl;
    }    
}

The C equivalent of the previous method is passing the array by pointer. This should not be confused with passing by the array's decayed pointer type (3), which is the common, popular method, albeit less safe than this one but more flexible. Like (1), use this method when all the dimensions of the array is fixed and known at compile-time. Note that when calling the function the array's address should be passed process_2d_array_pointer(&a) and not the address of the first element by decay process_2d_array_pointer(a).

前一个方法的C等价于通过指针传递数组。这不应该与传递数组的衰减指针类型(3)混淆,后者是常见的、流行的方法,虽然不如这个方法安全,但更灵活。与(1)类似,当数组的所有维数都固定且在编译时已知时,使用此方法。注意,在调用函数时,数组的地址应该通过process_2d_array_pointer()传递,而不是通过衰变process_2d_array_pointer(a)传递第一个元素的地址。

Variable Size

These are inherited from C but are less safe, the compiler has no way of checking, guaranteeing that the caller is passing the required dimensions. The function only banks on what the caller passes in as the dimension(s). These are more flexible than the above ones since arrays of different lengths can be passed to them invariably.

这些是从C继承而来的,但是安全性较差,编译器没有检查的方法,保证调用者正在传递所需的维度。该函数只存储调用者作为维度传入的内容。由于不同长度的数组总是可以传递给它们,所以它们比上面的数组更灵活。

It is to be remembered that there's no such thing as passing an array directly to a function in C [while in C++ they can be passed as a reference (1)]; (2) is passing a pointer to the array and not the array itself. Always passing an array as-is becomes a pointer-copy operation which is facilitated by array's nature of decaying into a pointer.

要记住,不存在直接将数组传递给C中的函数的情况[而在c++中,数组可以作为引用(1)传递];(2)向数组而不是数组本身传递指针。始终按原样传递一个数组就变成了指针复制操作,这是由于数组的衰减特性所促成的。

3. Pass by (value) a pointer to the decayed type

3所示。传递(值)一个指向衰减类型的指针

// int array[][10] is just fancy notation for the same thing
void process_2d_array(int (*array)[10], size_t rows)
{
    std::cout << __func__ << std::endl;
    for (size_t i = 0; i < rows; ++i)
    {
        std::cout << i << ": ";
        for (size_t j = 0; j < 10; ++j)
            std::cout << array[i][j] << '\t';
        std::cout << std::endl;
    }
}

Although int array[][10] is allowed, I'd not recommend it over the above syntax since the above syntax makes it clear that the identifier array is a single pointer to an array of 10 integers, while this syntax looks like it's a 2D array but is the same pointer to an array of 10 integers. Here we know the number of elements in a single row (i.e. the column size, 10 here) but the number of rows is unknown and hence to be passed as an argument. In this case there's some safety since the compiler can flag when a pointer to an array with second dimension not equal to 10 is passed. The first dimension is the varying part and can be omitted. See here for the rationale on why only the first dimension is allowed to be omitted.

虽然int[]数组允许[10],我不建议在上述语法因为上面的语法很清楚,标识符数组是一个指针指向一个10的整数数组,而这种语法看起来是一个二维数组,但相同的10个整数指针指向一个数组。在这里,我们知道一行中的元素数量(即列大小,这里是10),但是行数是未知的,因此要作为参数传递。在这种情况下,有一些安全性,因为当传递到第二个维度不等于10的数组的指针时,编译器可以标记。第一个维度是变化的部分,可以省略。在这里可以看到为什么只允许第一个维度被省略。

4. Pass by pointer to a pointer

4所示。通过指针指向指针

// int *array[10] is just fancy notation for the same thing
void process_pointer_2_pointer(int **array, size_t rows, size_t cols)
{
    std::cout << __func__ << std::endl;
    for (size_t i = 0; i < rows; ++i)
    {
        std::cout << i << ": ";
        for (size_t j = 0; j < cols; ++j)
            std::cout << array[i][j] << '\t';
        std::cout << std::endl;
    }
}

Again there's an alternative syntax of int *array[10] which is the same as int **array. In this syntax the [10] is ignored as it decays into a pointer thereby becoming int **array. Perhaps it is just a cue to the caller that the passed array should have at least 10 columns, even then row count is required. In any case the compiler doesn't flag for any length/size violations (it only checks if the type passed is a pointer to pointer), hence requiring both row and column counts as parameter makes sense here.

同样,int *array[10]的另一种语法与int **array相同。在此语法中,当[10]衰减成指针时,将被忽略,从而成为int **数组。也许这只是给调用者一个提示,即所传递的数组应该至少有10列,即使需要行数。在任何情况下,编译器都不会标记任何长度/大小违规(它只检查传递的类型是否为指针的指针),因此这里需要行和列计数作为参数。

Note: (4) is the least safest option since it hardly has any type check and the most inconvenient. One cannot legitimately pass a 2D array to this function; C-FAQ condemns the usual workaround of doing int x[5][10]; process_pointer_2_pointer((int**)&x[0][0], 5, 10); as it may potentially lead to undefined behaviour due to array flattening. The right way of passing an array in this method brings us to the inconvenient part i.e. we need an additional (surrogate) array of pointers with each of its element pointing to the respective row of the actual, to-be-passed array; this surrogate is then passed to the function (see below); all this for getting the same job done as the above methods which are more safer, cleaner and perhaps faster.

注:(4)是最不安全的选项,因为它几乎没有任何类型检查,而且最不方便。不能合法地将2D数组传递给这个函数;C-FAQ谴责做int x[5][10]的常见做法;process_pointer_2_pointer((int * *)x[0][0],5、10);因为它可能导致由于阵列扁平化而导致的未定义行为。在此方法中传递数组的正确方式将我们带到不方便的部分,即我们需要一个额外的指针(代理)数组,其每个元素都指向实际要传递的数组的相应行;然后将该代理传递给函数(见下面);所有这些都是为了完成与上述方法相同的工作,这些方法更安全、更干净,而且可能更快。

Here's a driver program to test the above functions:

下面是一个测试上述功能的驱动程序:

#include <iostream>

// copy above functions here

int main()
{
    int a[5][10] = { { } };
    process_2d_array_template(a);
    process_2d_array_pointer(&a);    // <-- notice the unusual usage of addressof (&) operator on an array
    process_2d_array(a, 5);
    // works since a's first dimension decays into a pointer thereby becoming int (*)[10]

    int *b[5];  // surrogate
    for (size_t i = 0; i < 5; ++i)
    {
        b[i] = a[i];
    }
    // another popular way to define b: here the 2D arrays dims may be non-const, runtime var
    // int **b = new int*[5];
    // for (size_t i = 0; i < 5; ++i) b[i] = new int[10];
    process_pointer_2_pointer(b, 5, 10);
    // process_2d_array(b, 5);
    // doesn't work since b's first dimension decays into a pointer thereby becoming int**
}

#3


33  

A modification to shengy's first suggestion, you can use templates to make the function accept a multi-dimensional array variable (instead of storing an array of pointers that have to be managed and deleted):

对于shengy的第一个建议,您可以使用模板使函数接受一个多维数组变量(而不是存储一个必须管理和删除的指针数组):

template <size_t size_x, size_t size_y>
void func(double (&arr)[size_x][size_y])
{
    printf("%p\n", &arr);
}

int main()
{
    double a1[10][10];
    double a2[5][5];

    printf("%p\n%p\n\n", &a1, &a2);
    func(a1);
    func(a2);

    return 0;
}

The print statements are there to show that the arrays are getting passed by reference (by displaying the variables' addresses)

打印语句显示数组是通过引用(通过显示变量的地址)传递的

#4


19  

You can create a function template like this:

您可以创建这样的函数模板:

template<int R, int C>
void myFunction(double (&myArray)[R][C])
{
    myArray[x][y] = 5;
    etc...
}

Then you have both dimension sizes via R and C. A different function will be created for each array size, so if your function is large and you call it with a variety of different array sizes, this may be costly. You could use it as a wrapper over a function like this though:

然后通过R和c可以得到两个维度大小,每个数组大小都会创建一个不同的函数,所以如果函数很大,并且使用不同的数组大小调用它,这可能会很昂贵。您可以将它作为这样的函数的包装:

void myFunction(double * arr, int R, int C)
{
    arr[x * C + y] = 5;
    etc...
}

It treats the array as one dimensional, and uses arithmetic to figure out the offsets of the indexes. In this case, you would define the template like this:

它将数组视为一维,并使用算术方法计算索引的偏移量。在这种情况下,您可以这样定义模板:

template<int C, int R>
void myFunction(double (&myArray)[R][C])
{
    myFunction(*myArray, R, C);
}

#5


8  

anArray[10][10] is not a pointer to a pointer, it is a contiguous chunk of memory suitable for storing 100 values of type double, which compiler knows how to address because you specified the dimensions. You need to pass it to a function as an array. You can omit the size of the initial dimension, as follows:

anArray[10][10]不是指向指针的指针,而是适合存储100个类型为double的值的连续内存块,编译器知道如何寻址,因为您指定了维度。您需要将它作为数组传递给函数。可以忽略初始维度的大小,如下所示:

void f(double p[][10]) {
}

However, this will not let you pass arrays with the last dimension other than ten.

但是,这将不会让您传递带有除10以外的最后一个维度的数组。

The best solution in C++ is to use std::vector<std::vector<double> >: it is nearly as efficient, and significantly more convenient.

在c++中最好的解决方案是使用std::vector <:vector> >:它几乎是高效的,而且非常方便。

#6


6  

Single dimensional array decays to a pointer pointer pointing to the first element in the array. While a 2D array decays to a pointer pointing to first row. So, the function prototype should be -

单维数组衰减为指向数组中第一个元素的指针指针。当一个二维数组衰减到指向第一行的指针。因此,函数原型应该是-

void myFunction(double (*myArray) [10]);

I would prefer std::vector over raw arrays.

与原始数组相比,我更喜欢std::vector。

#7


6  

You can do something like this...

你可以做这样的事情…

#include<iostream>

using namespace std;

//for changing values in 2D array
void myFunc(double *a,int rows,int cols){
    for(int i=0;i<rows;i++){
        for(int j=0;j<cols;j++){
            *(a+ i*rows + j)+=10.0;
        }
    }
}

//for printing 2D array,similar to myFunc
void printArray(double *a,int rows,int cols){
    cout<<"Printing your array...\n";
    for(int i=0;i<rows;i++){
        for(int j=0;j<cols;j++){
            cout<<*(a+ i*rows + j)<<"  ";
        }
    cout<<"\n";
    }
}

int main(){
    //declare and initialize your array
    double a[2][2]={{1.5 , 2.5},{3.5 , 4.5}};

    //the 1st argument is the address of the first row i.e
    //the first 1D array
    //the 2nd argument is the no of rows of your array
    //the 3rd argument is the no of columns of your array
    myFunc(a[0],2,2);

    //same way as myFunc
    printArray(a[0],2,2);

    return 0;
}

Your output will be as follows...

您的输出将如下…

11.5  12.5
13.5  14.5

#8


6  

Surprised that no one mentioned this yet, but you can simply template on anything 2D supporting [][] semantics.

还没有人提到这一点,但您可以在任何支持[][][]语义的2D模板上简单地使用它。

template <typename TwoD>
void myFunction(TwoD& myArray){
     myArray[x][y] = 5;
     etc...
}

// call with
double anArray[10][10];
myFunction(anArray);

It works with any 2D "array-like" datastructure, such as std::vector<std::vector<T>>, or a user defined type to maximize code reuse.

它适用于任何2D“arraylike”数据结构,如std::vector <:vector> >,或用户定义的类型,以最大化代码重用。

#9


1  

One important thing for passing multidimensional arrays is:

传递多维数组的一个重要事项是:

  • First array dimension need not be specified.
  • 不需要指定第一个数组维度。
  • Second(any any further)dimension must be specified.
  • 第二(任何其他)维度必须指定。

1.When only second dimension is available globally (either as a macro or as a global constant)

1。当只有第二个维度是全局可用的(可以是宏,也可以是全局常量)

`const int N = 3;

`void print(int arr[][N], int m)
{
int i, j;
for (i = 0; i < m; i++)
  for (j = 0; j < N; j++)
    printf("%d ", arr[i][j]);
}`

int main()
{
int arr[][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
print(arr, 3);
return 0;
}`

2.Using a single pointer: In this method,we must typecast the 2D array when passing to function.

2。使用一个指针:在这个方法中,我们必须在传递给函数时进行2D数组的排版。

`void print(int *arr, int m, int n)
{
int i, j;
for (i = 0; i < m; i++)
  for (j = 0; j < n; j++)
    printf("%d ", *((arr+i*n) + j));
 }

`int main()
{
int arr[][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
int m = 3, n = 3;

// We can also use "print(&arr[0][0], m, n);"
print((int *)arr, m, n);
return 0;
}`

#10


0  

You can use template facility in C++ to do this. I did something like this :

您可以使用c++中的模板工具来实现这一点。我做了这样的事情:

template<typename T, size_t col>
T process(T a[][col], size_t row) {
...
}

the problem with this approach is that for every value of col which you provide, the a new function definition is instantiated using the template. so,

这种方法的问题是,对于您提供的每一个col值,使用模板实例化一个新的函数定义。所以,

int some_mat[3][3], another_mat[4,5];
process(some_mat, 3);
process(another_mat, 4);

instantiates the template twice to produce 2 function definitions (one where col = 3 and one where col = 5).

实例化模板两次以生成两个函数定义(一个在col = 3处,另一个在col = 5处)。

#11


-1  

We can use several ways to pass a 2D array to a function:

我们可以用几种方法将二维数组传递给函数:

  • Using single pointer we have to typecast the 2D array.

    使用单个指针,我们必须对2D数组进行排版。

    #include<bits/stdc++.h>
    using namespace std;
    
    
    void func(int *arr, int m, int n)
    {
        for (int i=0; i<m; i++)
        {
           for (int j=0; j<n; j++)
           {
              cout<<*((arr+i*n) + j)<<" ";
           }
           cout<<endl;
        }
    }
    
    int main()
    {
        int m = 3, n = 3;
        int arr[m][n] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
        func((int *)arr, m, n);
        return 0;
    }
    
  • Using double pointer In this way, we also typecast the 2d array

    用这种方式使用双指针,我们也排版二维数组

    #include<bits/stdc++.h>
    using namespace std;

   void func(int **arr, int row, int col)
   {
      for (int i=0; i<row; i++)
      {
         for(int j=0 ; j<col; j++)
         {
           cout<<arr[i][j]<<" ";
         }
         printf("\n");
      }
   }

  int main()
  {
     int row, colum;
     cin>>row>>colum;
     int** arr = new int*[row];

     for(int i=0; i<row; i++)
     {
        arr[i] = new int[colum];
     }

     for(int i=0; i<row; i++)
     {
         for(int j=0; j<colum; j++)
         {
            cin>>arr[i][j];
         }
     }
     func(arr, row, colum);

     return 0;
   }