如何在 C 中分配二维指针数组

发布于 2024-08-11 20:25:45 字数 38 浏览 5 评论 0原文

我正在尝试使指针指向二维指针数组。语法是什么以及如何访问元素?

I'm trying to make a pointer point to a 2D array of pointers. What is the syntax and how would I access elements?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

楠木可依 2024-08-18 20:25:45

根据法律规定,具体操作方法如下:

// Create 2D array of pointers:
int*** array2d = new (int**)[rows];
for (int i = 0; i < rows; ++i) {
  array2d[i] = new (int*)[cols];
}

// Null out the pointers contained in the array:
for (int i = 0; i < rows; ++i) {
  for (int j = 0; j < cols; ++j) {
    array2d[i][j] = NULL;
  }
}

小心地以正确的顺序单独删除包含的指针、行数组和列数组。

然而,在 C++ 中,您更频繁地创建一个类,在内部管理一维指针数组并重载函数调用运算符以提供二维索引。这样你就真正拥有了一个连续的指针数组,而不是一个指针数组的数组。

By the letter of the law, here's how to do it:

// Create 2D array of pointers:
int*** array2d = new (int**)[rows];
for (int i = 0; i < rows; ++i) {
  array2d[i] = new (int*)[cols];
}

// Null out the pointers contained in the array:
for (int i = 0; i < rows; ++i) {
  for (int j = 0; j < cols; ++j) {
    array2d[i][j] = NULL;
  }
}

Be careful to delete the contained pointers, the row arrays, and the column array all separately and in the correct order.

However, more frequently in C++ you'd create a class that internally managed a 1D array of pointers and overload the function call operator to provide 2D indexing. That way you're really have a contiguous array of pointers, rather than an array of arrays of pointers.

错々过的事 2024-08-18 20:25:45

这取决于。它可以很简单:

int main()
{
    int*   data[10][20]; // Fixed size known at compile time

    data[2][3] = new int(4);
}

如果您希望在运行时动态大小,您需要做一些工作。
但是 Boost 可以满足您的需求:

int main()
{
   int  x;
   int  y;
   getWidthAndHeight(x,y);

   // declare a 2D array of int*
   boost::multi_array<int*,2>   data(boost::extents[x][y]);

   data[2][3] = new int(6);
}

如果您对 锯齿状数组可以动态增长:

int main()
{
    std::vector<std::vector<int*> >   data;

    data.push_back(std::vector<int*>(10,NULL));
    data[0][3] = new int(7);
}

注意:在上述所有内容中。我假设数组不拥有指针。因此,它没有对其包含的指针进行任何管理(尽管为了简洁起见,我在示例中使用了 new int() )。要正确进行内存管理,您需要做更多的工作。

It depends. It can be as simple as:

int main()
{
    int*   data[10][20]; // Fixed size known at compile time

    data[2][3] = new int(4);
}

If you want dynamic sizes at runtime you need to do some work.
But Boost has you covered:

int main()
{
   int  x;
   int  y;
   getWidthAndHeight(x,y);

   // declare a 2D array of int*
   boost::multi_array<int*,2>   data(boost::extents[x][y]);

   data[2][3] = new int(6);
}

If you are fine with jagged arrays that can grow dynamically:

int main()
{
    std::vector<std::vector<int*> >   data;

    data.push_back(std::vector<int*>(10,NULL));
    data[0][3] = new int(7);
}

Note: In all the above. I assume that the array does not own the pointer. Thus it has not been doing any management on the pointers it contains (though for brevity I have been using new int() in the examples). To do memory management correctly you need to do some more work.

花开浅夏 2024-08-18 20:25:45
int *pointerArray[X][Y];
int **ptrToPointerArray = pointerArray;

这就是创建真正的(内存中连续的)多维数组的方法。

但要意识到,一旦将多维数组转换为这样的指针,您就失去了自动索引它的能力。您必须手动执行索引的多维部分:

int *pointerArray[8][6]; // declare array of pointers
int **ptrToPointerArray = &pointerArray[0][0]; // make a pointer to the array
int *foo = pointerArray[3][1]; // access one element in the array
int *bar = *(ptrToPointerArray + 3*8 + 1); // manually perform row-major indexing for 2d array

foo == bar; // true
int *baz = ptrToPointerArray[3][1]; // syntax error
int *pointerArray[X][Y];
int **ptrToPointerArray = pointerArray;

That's how you make a true (contiguous in memory) multidimensional array.

But realize that once you cast a multidimensional array to a pointer like that, you lose the ability to index it automatically. You would have to do the multidimensional part of the indexing manually:

int *pointerArray[8][6]; // declare array of pointers
int **ptrToPointerArray = &pointerArray[0][0]; // make a pointer to the array
int *foo = pointerArray[3][1]; // access one element in the array
int *bar = *(ptrToPointerArray + 3*8 + 1); // manually perform row-major indexing for 2d array

foo == bar; // true
int *baz = ptrToPointerArray[3][1]; // syntax error
待天淡蓝洁白时 2024-08-18 20:25:45
double** array = new double*[rowCnt];
for (int row = 0; row < rowCnt; ++row)
  array[row] = new double[colCnt];
for (int row = 0; row < rowCnt; ++row)
  for (int col = 0; col < colCnt; ++col)
    array[row][col] = 0;
double** array = new double*[rowCnt];
for (int row = 0; row < rowCnt; ++row)
  array[row] = new double[colCnt];
for (int row = 0; row < rowCnt; ++row)
  for (int col = 0; col < colCnt; ++col)
    array[row][col] = 0;
溺ぐ爱和你が 2024-08-18 20:25:45

你可以尝试 Boost::MultiArray。

请查看此页面了解详细信息。

You could try Boost::MultiArray.

Check out this page for details.

长梦不多时 2024-08-18 20:25:45

:)

我在我写的一段代码中曾经有过这些。

当第一个 bug 泄露出去时,我成了团队的笑柄。最重要的是,我们使用匈牙利表示法,导致像 papChannel 这样的名称 - 指向指针数组的指针......

这不太好。最好使用 typedef 来定义“行列”,反之亦然。也使索引更加清晰。

typedef int Cell;
typedef Cell Row[30];
typedef Row Table[20];

Table * pTable = new Table;

for( Row* pRow = *pTable; pRow != *pTable+_countof(*pTable); ++pRow ) {
   for( Cell* pCell = *pRow; pCell != *pRow + _countof(*pRow); ++pCell ) {
     ... do something with cells.
   }
}

:)

I had these once in a piece of code I wrote.

I was the laughing stock of the team when the first bugs leaked out. On top of that we use Hungarian notation, leading to a name like papChannel - a pointer to an array of pointers...

It's not nice. It's nicer to use typedefs to define a 'row of columns' or vice versa. Makes indexing more clear, too.

typedef int Cell;
typedef Cell Row[30];
typedef Row Table[20];

Table * pTable = new Table;

for( Row* pRow = *pTable; pRow != *pTable+_countof(*pTable); ++pRow ) {
   for( Cell* pCell = *pRow; pCell != *pRow + _countof(*pRow); ++pCell ) {
     ... do something with cells.
   }
}
若沐 2024-08-18 20:25:45

您可以定义向量的向量:

typedef my_type *my_pointer;

typedef vector<vector<my_pointer> > my_pointer2D;

然后创建一个从 my_pointer2D 派生的类,例如:

class PointersField: public my_pointer2D
{
  PointsField(int n, int m)
  {
     // Resize vectors....
  }
}

PointsField pf(10,10); // Will create a 10x10 matrix of my_pointer

You can define a vector of vectors:

typedef my_type *my_pointer;

typedef vector<vector<my_pointer> > my_pointer2D;

Than create a class derived from my_pointer2D, like:

class PointersField: public my_pointer2D
{
  PointsField(int n, int m)
  {
     // Resize vectors....
  }
}

PointsField pf(10,10); // Will create a 10x10 matrix of my_pointer
喜你已久 2024-08-18 20:25:45

我更喜欢使用 () 运算符。造成这种情况的原因有很多(C++ 常见问题解答 13.10) 。如果您愿意,请将内部表示更改为 std::vector

template <class T, int WIDTH, int HIEGHT>
class Array2d
{
public:
    const T& operator ()(size_t col, size_t row) const
    {
        // Assert col < WIDTH and row < HIEGHT
        return m_data [( row * WIDTH + col)];
    }
    T& operator ()(size_t col, size_t row)
    {
        // Assert col < WIDTH and row < HIEGHT
        return m_data [( row * WIDTH + col)];
    }
private:
T m_data[WIDTH * HIEGHT];
};

您可以像这样使用它:

Array2d< Object*, 10, 10 > myObjectArray;
myObjectArray(5,6) = new Object();

I prefer to use the () operator. There are lots of reasons for this (C++ FAQs 13.10). Change the internal representation to a std::vector if you like:

template <class T, int WIDTH, int HIEGHT>
class Array2d
{
public:
    const T& operator ()(size_t col, size_t row) const
    {
        // Assert col < WIDTH and row < HIEGHT
        return m_data [( row * WIDTH + col)];
    }
    T& operator ()(size_t col, size_t row)
    {
        // Assert col < WIDTH and row < HIEGHT
        return m_data [( row * WIDTH + col)];
    }
private:
T m_data[WIDTH * HIEGHT];
};

You can use it like this:

Array2d< Object*, 10, 10 > myObjectArray;
myObjectArray(5,6) = new Object();
歌枕肩 2024-08-18 20:25:45

看我的代码。它适用于我的 FC9 x86_64 系统:

#include <stdio.h>

template<typename t>
struct array_2d {
        struct array_1d {
                t *array;
                array_1d(void) { array = 0; }
                ~array_1d()
                {
                    if (array) {
                         delete[] array;
                         array = 0;
                    }
                }
                t &operator[](size_t index) { return array[index]; }
        } *array;
        array_2d(void) { array = 0; }
        array_2d(array_2d<t> *a) { array = a->array; a->array = 0; }
        void init(size_t a, size_t b)
        {
                array = new array_1d[a];
                for (size_t i = 0; i < a; i++) {
                        array[i].array = new t[b];
                }
        }
        ~array_2d()
        {
                if (array) {
                        delete[] array;
                        array = 0;
                }
        }
        array_1d &operator[](size_t index) { return array[index]; }
};

int main(int argc, char **argv)
{
        array_2d<int> arr = new array_2d<int>;
        arr.init(16, 8);

        arr[8][2] = 18;
        printf("%d\n",
                arr[8][2]
                );

        return 0;
}

Effo UPD:对“这不是一个指向数组的指针数组吗?”的回应,添加了指针数组的示例,非常简单:

int main(int argc, char **argv)
{
        array_2d<int*> parr = new array_2d<int*>;
        int i = 10;
        parr.init(16, 8);
        parr[10][5] = &i;
        printf("%p %d\n",
                parr[10][5],
                parr[10][5][0]
                );

        return 0;
}

我是否仍然误解了你的问题?

你甚至可以

typedef array_2d<int*> cell_type;
typedef array_2d<cell_type*> array_type;

int main(int argc, char **argv)
{
    array_type parr = new array_type;
    parr.init(16, 8);
    parr[10][5] = new cell_type;
    cell_type *cell = parr[10][5];
    cell->init(8, 16);
    int i = 10;
    (*cell)[2][2] = &i;

    printf("%p %d\n",
            (*cell)[2][2],
            (*cell)[2][2][0]
            );

    delete cell;

    return 0;
}

它也适用于我的 FC9 x86_64 系统。

See my code. It works on my FC9 x86_64 system:

#include <stdio.h>

template<typename t>
struct array_2d {
        struct array_1d {
                t *array;
                array_1d(void) { array = 0; }
                ~array_1d()
                {
                    if (array) {
                         delete[] array;
                         array = 0;
                    }
                }
                t &operator[](size_t index) { return array[index]; }
        } *array;
        array_2d(void) { array = 0; }
        array_2d(array_2d<t> *a) { array = a->array; a->array = 0; }
        void init(size_t a, size_t b)
        {
                array = new array_1d[a];
                for (size_t i = 0; i < a; i++) {
                        array[i].array = new t[b];
                }
        }
        ~array_2d()
        {
                if (array) {
                        delete[] array;
                        array = 0;
                }
        }
        array_1d &operator[](size_t index) { return array[index]; }
};

int main(int argc, char **argv)
{
        array_2d<int> arr = new array_2d<int>;
        arr.init(16, 8);

        arr[8][2] = 18;
        printf("%d\n",
                arr[8][2]
                );

        return 0;
}

Effo UPD: a response to "Isn't that an array of pointers to arrays?", adding the example of array of pointers, very simple:

int main(int argc, char **argv)
{
        array_2d<int*> parr = new array_2d<int*>;
        int i = 10;
        parr.init(16, 8);
        parr[10][5] = &i;
        printf("%p %d\n",
                parr[10][5],
                parr[10][5][0]
                );

        return 0;
}

Did I still misunderstand your question?

And you could even

typedef array_2d<int*> cell_type;
typedef array_2d<cell_type*> array_type;

int main(int argc, char **argv)
{
    array_type parr = new array_type;
    parr.init(16, 8);
    parr[10][5] = new cell_type;
    cell_type *cell = parr[10][5];
    cell->init(8, 16);
    int i = 10;
    (*cell)[2][2] = &i;

    printf("%p %d\n",
            (*cell)[2][2],
            (*cell)[2][2][0]
            );

    delete cell;

    return 0;
}

It also works on my FC9 x86_64 system.

兔姬 2024-08-18 20:25:45

如果您需要二维数组的大小是动态的(即运行时已知的尺寸),您可以使用专门的库。
像Boost.MultiArray(其他答案),或Multi

#include <multi/array.hpp>

namespace multi = boost::multi;

int main() { 

    multi::array<double*, 2> A({3, 4}, nullptr);

    for(auto& e : A.elements()) {
        e = new double(99.);
    }

    assert( *A[1][2] == 99. );

    auto B = A;  // this will copy the pointers

    for(auto& e : B.elements()) {
        delete e;
    }
}

https://godbolt.org/z/G6WrP9vKW

If you need the 2D array to be dynamic in size (i.e. dimensions known at runtime) you can use a specialized library for that.
Like Boost.MultiArray (other answer), or Multi:

#include <multi/array.hpp>

namespace multi = boost::multi;

int main() { 

    multi::array<double*, 2> A({3, 4}, nullptr);

    for(auto& e : A.elements()) {
        e = new double(99.);
    }

    assert( *A[1][2] == 99. );

    auto B = A;  // this will copy the pointers

    for(auto& e : B.elements()) {
        delete e;
    }
}

https://godbolt.org/z/G6WrP9vKW

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文