简体   繁体   English

C ++多维数组和指向指针表的指针

[英]C++ multidimensional array and pointers to table of pointers

Here is the thing. 这是东西。 I can completely understand a concept of a multidimensional array (let's consider 2D for a while) made by pointer to array to pointers and so on... 我可以完全理解由指向数组的指针等组成的多维数组的概念(让我们考虑一下二维)。

We do something like this: 我们做这样的事情:

// we can use dynamically defined size n and m
int n = 3, m = 5 ;
int **T = new int *[n];
for (int i = 0 ; i < n ; ++i)
    T[i] = new int[m];

What we got is: (Check if I'm right here) 我们得到的是:(检查我是否在这里)

  • 3 blocks of memory of 5 ints, placed somewhere in memory 5个整数的3个内存块,放置在内存中的某个位置
  • One additional block of memory of same size as number of the blocks of ints (number of rows). 与int块数(行数)相同大小的另一块内存。 This block is an array of pointers (usually 4 bytes for pointer like int) to those int rows. 此块是一个指向这些int行的指针(通常为4个字节,用于类似int的指针)的数组。
  • What we are interested in most - that is T which is of type (**T) - a pointer to pointer. 我们最感兴趣的是-指针(T),它是(** T)类型的指针。 Which is exactly a pointer to an array of pointer, because in C++ an array is in fact a pointer pointing to a block of memory so t[] or t[0] means *t, and t[x] means *(t+x). 这正是指向指针数组的指针,因为在C ++中,数组实际上是指向内存块的指针,因此t []或t [0]表示* t,t [x]表示*(t + X)。

Now the problem is when we do sth like this: 现在的问题是,当我们这样做时:

int n = 3, m = 5 ;
int T[n][m] ;

What we've got is not what w could have doing the thing I showed before. 我们所能做的并不是我以前展示过的事情。 We get sth strange. 我们有些奇怪。 What is T? 什么是T? When printfing T, we get the same value as T[0]. 当打印T时,我们得到与T [0]相同的值。 It looks like we reserved a block of ints sized n*m without additional array of pointers to rows. 似乎我们保留了一个大小为n * m的整数块,而没有指向行的附加指针数组。

My question is: does the compiler remembers the dimension of the array and number of rows and columns? 我的问题是:编译器会记住数组的维数以及行和列的数量吗? And when asking for T[i][j] it actually asks for *(T+i*n+j) so this n is stored somewhere? 当要求T [i] [j]时,实际上要求的是*(T + i * n + j),所以这n存储在某个地方吗? The problem is when we are trying to pass this thing (T) to a function. 问题是当我们试图将此东西(T)传递给函数时。 I dont know why but if n and m were constants its possible to pass T as a pointer to this array to function like in this program: 我不知道为什么,但是如果n和m是常量,则可以将T作为指向此数组的指针传递,以使其在此程序中起作用:

#include <stdio.h>
const int n = 3, m = 4 ; // this is constant!
void add_5(int K[][m])
{
    for (int i = 0 ; i < n ; ++i)
        for (int j = 0 ; j < m ; j++)
            K[i][j] += 5 ;
}
int main()
{
    // n x m array the most straight forward method
    int T[n][m] ;
    for (int i = 0 ; i < n ; ++i)
        for (int j = 0 ; j < m ; ++j)
            T[i][j] = i*m + j ;

    for (int i = 0 ; i < n ; ++i)
    {
        for (int j = 0 ; j < m ; j++)
            printf("%d ",T[i][j]) ;
        printf("\n") ;
    }
    printf("\n") ;

    // adding 5 to all cells
    add_5(T) ;
    printf("it worked!!\n") ;

    for (int i = 0 ; i < n ; ++i)
    {
        for (int j = 0 ; j < m ; j++)
            printf("%d ",T[i][j]) ;
        printf("\n") ;
    }

    int ss ;
    scanf("%d",&ss) ;
}

But if n and m aren't constant we cant. 但是,如果n和m不是常数,我们就不能。 So what I need is to pass dynamically created multidimensional array's pointer to a function without manually allocating memory for that. 因此,我需要的是将动态创建的多维数组的指针传递给函数,而无需为此手动分配内存。 How to do this? 这个怎么做?

in C++ an array is in fact a pointer pointing to a block of memory 在C ++中,数组实际上是指向内存块的指针

Absolutely not. 绝对不。 An array is entirely separate from a pointer. 数组与指针完全分开。 The reason you might have this confusion is because of a standard conversion called array-to-pointer conversion. 您可能会感到困惑的原因是由于称为数组到指针转换的标准转换。 Consider: 考虑:

int arr[10];

The variable arr denotes an array. 变量arr表示一个数组。 It's not a pointer at all. 根本不是指针。 It just so happens that in many circumstances, the name of an array will be converted to a pointer to its first element. 碰巧的是,在许多情况下,数组的名称将转换为指向其第一个元素的指针。 That is, the conversion turns it into an int* . 也就是说,转换将其转换为int*

int T[n][m] ;

In this case, T is an "array of n array of m int s". 在这种情况下, T是“ m intn数组的数组”。 You mentioned that printing both T and T[0] give the same result, and this is due to array-to-pointer conversion. 您提到打印TT[0]得到相同的结果,这是由于数组到指针的转换所致。

  1. The expression T can be converted to a pointer to the first element; 表达式T可以转换为指向第一个元素的指针; that is, an int (*)[m] , because the first element of T is itself an array with m elements. 也就是int (*)[m] ,因为T的第一个元素本身就是一个包含m元素的数组。

  2. The expression T[0] can be converted to a pointer to the first element of the first subarray. 表达式T[0]可以转换为指向第一个子数组的第一个元素的指针。 So you get a pointer to the element T[0][0] of type int* . 因此,您获得了一个指向int*类型的元素T[0][0]的指针。

These pointers hold the same address because of the way an array is laid out in memory. 由于数组在内存中的布局方式,这些指针具有相同的地址。 The address that an array begins at is the same address as the first element of that array. 数组开始的地址与该数组的第一个元素的地址相同。 However, the pointers do not behave in the same way. 但是,指针的行为方式不同。 If you increment the pointer resulting from T , you move along to the next subarray. 如果增加由T产生的指针,则移至下一个子数组。 If you increment the pointer resulting from T[0] , you move along to the next int . 如果递增由T[0]得出的指针,则移至下一个int

It might help you to look at a diagram of how a 2D array is laid out in memory compared to a dynamically allocated "2D array". 与动态分配的“ 2D数组”相比,它可能有助于您查看内存中2D数组的布局图。 A 3-by-3 2D array would look like this: 3×3 2D数组如下所示:

  0,0   0,1   0,2   1,0   1,1   1,2   2,0   2,1   2,2
┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐
│ int │ int │ int │ int │ int │ int │ int │ int │ int │
└─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘

Whereas if you dynamically allocated a 3-by-3 "2D array": 而如果您动态分配了一个3×3的“ 2D数组”:

┌─────┐
│     │ // The int**
└──╂──┘
   ┃
   ▼
┌─────┬─────┬─────┐
│     │     │     ┿━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓  // An array of int*
└──╂──┴──╂──┴─────┘                            ┃
   ┃     ┗━━━━━━━━━━━━━━━┓                     ┃
   ▼                     ▼                     ▼
┌─────┬─────┬─────┐   ┌─────┬─────┬─────┐   ┌─────┬─────┬─────┐
│ int │ int │ int │   │ int │ int │ int │   │ int │ int │ int │ // Arrays of ints
└─────┴─────┴─────┘   └─────┴─────┴─────┘   └─────┴─────┴─────┘
  0,0   0,1   0,2       1,0   1,1   1,2       2,0   2,1   2,2

does the compiler remembers the dimension of the array and number of rows and columns? 编译器是否还记得数组的尺寸以及行和列的数量?

Yes, if you have a variable with array type, the size of the array is part of that type. 是的,如果您具有数组类型的变量,则数组的大小就是该类型的一部分。 The compiler always knows the type of a variable. 编译器始终知道变量的类型。

And when asking for T[i][j] it actually asks for *(T+i*n+j) so this n is stored somewhere? 当要求T [i] [j]时,实际上要求的是*(T + i * n + j),所以这n存储在某个地方吗?

The expression T[i][j] is equivalent to *(*(T + i) + j) . 表达式T[i][j]等于*(*(T + i) + j) Let's understand what this does. 让我们了解它的作用。 First, array-to-pointer conversion is undergone by T , giving an int (*)[m] . 首先,由T进行数组到指针的转换,得到int (*)[m] We then add i to this to move along to point at the i th subarray. 然后,我们将i添加到此以指向第i个子数组。 This is then dereferenced to get the subarray. 然后将其取消引用以获取子数组。 Next, this subarray also undergoes array-to-pointer conversion, giving an int* . 接下来,此子数组也将进行数组到指针的转换,得到一个int* You then add j to this to get a pointer to the j th int object in that subarray. 然后,向其添加j以获得指向该子数组中第jint对象的指针。 This is dereferenced to give that int . 取消引用以提供该int

The problem is when we are trying to pass this thing (T) to a function. 问题是当我们试图将此东西(T)传递给函数时。 I dont know why but if n and m were constants its possible to pass T as a pointer to this array to function 我不知道为什么,但是如果n和m是常量,则可以将T作为指向此数组的指针传递给函数

It's actually a lie. 这实际上是谎言。 You're not passing the 2D array to the function. 您没有将2D数组传递给函数。 In fact, there's no such thing as an array type argument. 实际上,没有像数组类型这样的参数。 Your argument int K[][m] is actually equivalent to int (*K)[m] . 您的参数int K[][m]实际上等效于int (*K)[m] That is, all array type arguments are transformed into pointers. 也就是说,所有数组类型参数都转换为指针。

So when you call this function with add_5(T) , you're not passing the array denoted by T . 因此,当您使用add_5(T)调用此函数时,没有传递T表示的数组。 T is actually undergoing array-to-pointer conversion to give you an int (*)[m] and this pointer is being passed into the function. T实际上正在进行数组到指针的转换,以为您提供一个int (*)[m]并且指针正在传递到函数中。

Here is an example of 2d dynamic array: 这是二维动态数组的示例:

const int Mapsize = n

    int** GameField2 = 0;

GameField2 = new int*[Mapsize];                 // memory alocation
for(int i = 0; i < Mapsize; i++)
    GameField2[i] = new int[Mapsize];

for(int j = 0; j < Mapsize; j++)                
    for(int i = 0; i < Mapsize; i++)
        GameField2[i][j] = 0;

if you wish to operate on this array on any function, simply pass the pointer like this: 如果您希望在任何函数上对该数组进行操作,只需传递如下指针:

int Whatver(int** GameField)
{
    GameField[a][b]=x;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM