2

如果我声明一个二维数组

int A[sz][sz];

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

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

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

如果它是二维数组,我如何创建数组然后分配一个指向该数组的指针。

我应该更清楚。我想返回一个指向指针的指针,这样它就不是指向二维数组的指针,而是类似int**.

4

3 回答 3

2

您的问题是,表单中的二维数组int**需要一个int*用于两步取消引用的数组,当您声明一个数组时,它根本不存在int A[sz][sz];.

您可以像这样自己构建它:

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

这可能看起来很荒谬,但根源于 C 处理数组的方式:A[i]is of type int ()[sz],它是 row 的子数组i。但是,当您在赋值中使用该数组时,它会衰减为指向该子数组中第一个元素的指针,该元素的类型为int*. 循环之后,Aandpointers是两个非常不同的东西(Ais的类型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。重要的是必须知道数组的实际大小,要么是编译时间常数,要么是与数组指针一起传递(如果它与数组指针,大小参数必须出现在数组指针之前)。

于 2013-09-17T22:00:08.557 回答
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 [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

于 2013-09-17T22:00:54.883 回答
0

你的问题的回答很奇怪。只需这样做:

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

*p = A[0];   // **p==A[0][0] , *(*p+1)==A[0][1]
于 2013-09-17T23:06:06.293 回答