指定指向2D数组的指针

时间:2013-09-17 21:43:28

标签: c++ arrays pointers

如果我声明一个2D数组

int A[sz][sz];

如何创建指向此对象的指针?

我问,因为我想通过指向函数的指针返回一个数组int**,但是我想在不知道大小的情况下构建数组。大小将作为参数传递。我想知道是否有办法在不使用动态分配的情况下执行此操作。

问题是如果我在函数内部执行类似int** A的操作,则会A没有关于我想要的大小的信息。

如果它是2D数组,我如何创建数组,然后指定一个指向该数组的指针。

我应该更清楚。我想返回指向指针的指针,因此它不是指向2D数组的指针,而是类似int**的指针。

3 个答案:

答案 0 :(得分:2)

您的问题是,int**形式的2D数组需要int*数组才能进行两步解除引用,当您使用int A[sz][sz];声明数组时,该数组根本不存在

您可以像这样自己构建:

int* pointers[sz];
for(size_t i = sz; i--; ) pointers[i] = A[i];

这可能看起来很荒谬,但根植于C处理数组的方式:A[i]属于int ()[sz]类型,它是行i的子数组。但是当您在赋值中使用该数组时,它衰减指向该子数组中第一个元素的指针,该元素的类型为int*。在循环之后,Apointers是两个非常不同的东西(A的类型是int ()[sz][sz]

旁注:你说你想从函数中返回它。如果您的数组是在堆栈上分配的,那么不能返回指向其数据的指针,它会在您的函数返回时消失。您只能返回指向具有static存储或属于另一个现有对象的对象的指针/引用。如果您不遵守此规定,则可能会导致堆栈损坏。

修改

关于C的一个鲜为人知的事实是,你实际上可以将指针传递给真正的C数组,而不仅仅是数组衰减的指针类型。这是一个小程序来证明这一点:

#include <stddef.h>
#include <stdio.h>

int (*foo(int size, int (*bar)[size][size], int y))[] {
    return &(*bar)[y];
}

int main() {
    int mySize = 30;
    int baz[mySize][mySize];
    int (*result)[mySize];
    result = foo(mySize, &baz, 15);
    printf("%ld\n", (size_t)result - (size_t)baz);
}

这个示例程序的预期输出是1800.重要的是必须知道数组的实际大小,或者通过编译时常量,或者通过与数组指针一起传递(如果它已经传递)与数组指针一起,size参数必须出现在数组指针之前。

答案 1 :(得分:1)

让我稍微充实你的问题。你提到:

  

我问,因为我想从一个函数返回一个数组[...]但是我   想要在不事先知道大小的情况下构建阵列。尺寸   将作为参数传递。我想知道是否有办法   这不使用动态分配。

对于我想从作为参数传递的函数大小返回一个数组,我觉得你可以在任何地方使用std::vector并调用当您需要访问底层数组(保证连续)时,它的.data()方法。例如:

std:vector<double> myfun(size_t N) {
 std::vector<double> r(N);
 // fill r[0], r[1], ..., r[N-1]
 return r;
}

// later on:
r.data(); // gives you a pointer to the underlying double[N]

对于我想在没有动态分配的情况下执行此操作,除非您在编译时知道大小,否则这是不可能的。如果是这种情况,那么就像以前一样,但使用std::array,它可以根据已知的编译时大小实现优化:

std::array<double, N> myfun() {
 std::array<double, N> r;
 // fill r[0], r[1], ..., r[N-1]
 return r;
}

// later on:
r.data(); // gives you a pointer to the underlying double[N]

为了通用,我实际上会使用一个能够处理任意容器的模板函数:

template<typename T>
void myfun(T& data) {
  for(int k=0; k<data.size(); k++) {
    // do stuff to data[k]
 }
}

// call as, for example:
std::vector<double> data(10);
myfun(data);

// or equally valid:
std::array<double, 10> data;
myfun(data);

最后,如果您正在使用二维数据,请记住,当您按行的主要顺序存储Matrix时:

Matrix [1, 2; 3 4] is stored as [1 2 3 4]

然后您可以通过调用(i, j)来引用矩阵的元素data[i * ncols + j]。例如:考虑一个三乘四的矩阵:

a b c d
e f g h
i j k l

元素(2, 2)(即:第三行,第三列,因为我们假设从零开始的C类型索引)计算为:M[2][2] = M[2 * 4 + 2] = M[10] = k。情况就是这样,因为它存储为:

 [a b c d e f g h i j  k  l]
 [0 1 2 3 4 5 6 7 8 9 10 11]

k是索引为10的元素。

答案 2 :(得分:0)

对你问题的回答很奇怪。就这样做:

int A[2][2];
int**p =NULL;

*p = A[0];   // **p==A[0][0] , *(*p+1)==A[0][1]