如果我声明一个2D数组
int A[sz][sz];
如何创建指向此对象的指针?
我问,因为我想通过指向函数的指针返回一个数组int**
,但是我想在不知道大小的情况下构建数组。大小将作为参数传递。我想知道是否有办法在不使用动态分配的情况下执行此操作。
问题是如果我在函数内部执行类似int** A
的操作,则会A
没有关于我想要的大小的信息。
如果它是2D数组,我如何创建数组,然后指定一个指向该数组的指针。
我应该更清楚。我想返回指向指针的指针,因此它不是指向2D数组的指针,而是类似int**
的指针。
答案 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*
。在循环之后,A
和pointers
是两个非常不同的东西(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]