将*指针转换为***指针

时间:2014-08-02 19:09:01

标签: c pointers

假设我有一个平坦的,动态分配的1d数组(我们称之为vector),它将包含一些3d数据。有没有办法创建另一个指针(让我们称之为tensor),它会“看到”vector为3d数组,所以我可以tensor[i][j][k]访问它?

我尝试了以下操作,但它不起作用:

int x, y, z; //Number of rows, cols, ...
double *vector;
double ***tensor;

x = 10; y = 10; z = 10;
vector = (double *) malloc(x * y * z * sizeof(double));

tensor = (double ***) vector;
tensor[0] = (double **) vector;
tensor[0][0] = (double *) vector;

for(j = 1; j < y; j++) {
    tensor[0][j] = tensor[0][j-1] + z;
}
for(i = 1; i < x; i++) {
    tensor[i] = tensor[i - 1] + y;
    tensor[i][0] = tensor[i - 1][0] + y * z;
    for(j = 1; j < y; j ++) {
        tensor[i][j] = tensor[i][j - 1] + z;
    }
}

tensor[0][0][0] = 1.0; //Segfaults here
tensor[0][0][1] = 2.0;
...

我做错了什么?

5 个答案:

答案 0 :(得分:8)

我可以举例说明将2d数组分配为指针数组加1d数据数组 在一个malloc

const int M = 100;
const int N = 200;
int **a = NULL;
int i, j;

a = malloc(M * sizeof(int*) + N * M * sizeof(int));
a[0] = (int*)(a + M);
for (i = 1; i < M; i++) {
    a[i] = a[0] + i * N;
}

//some code

free(a);

图片

enter image description here

并在两个mallocs中

const int M = 100;
const int N = 200;
int **a = NULL;
int i;

a = malloc(M * sizeof(int*));
a[0] = malloc(M * N * sizeof(int));
for (i = 1; i < M; i++) {
    a[i] = a[0] + i * N;
}

//Some code

free(a[0]);
free(a);

图像

enter image description here

以下是2个好处:第1个 - 快速分配,第二个 - [0]是1d数组的开头,因此您可以将其视为1d。是的 - 我懒得发布3d阵列的完整解决方案。

答案 1 :(得分:1)

由于您使用的是C而不是C ++,因此您可以使用真正的3D数组:

int x = 10, y = 10, z = 10;
double (*tensor)[y][z] = malloc(x * sizeof(*tensor));

tensor[0][0][0] = 1.0; //No segfaults here anymore...
tensor[0][0][1] = 2.0;
...

诀窍是将tensor定义为指向双精度数组数组的指针,而不是多级指针。效果几乎和你做的一样:

int x = 10, y = 10, z = 10;
double tensor[x][y][z];

tensor[0][0][0] = 1.0; //Might segfault, because we allocated a large 3D array on the stack.
tensor[0][0][1] = 2.0;
...

唯一的区别是分配了数组数组的位置 - 你不应该使用在堆栈上分配的更高版本,堆栈空间有点受限。但是,生成的3D阵列的内存布局在两种情况下都是相同的。

答案 2 :(得分:0)

您必须为指向tensor中存储的指针的指针分配内存。 tensor是指向指针的指针,所以它需要内存用于指向你正在分配的指针的所有指针。

示例:

double*** tensor = new double**[10]; // 10 double pointers are allocated

同样适用于下一个内在维度。

答案 3 :(得分:0)

你可以尝试一种替代方法,在这种方法中你不转换矢量,而是使用&#34;参见&#34;矢量作为张量。

double getValueFromTensor(double * vector,
                          size_t dim_x,
                          size_t dim_y,
                          size_t dim_z,
                          int x, int y, int z);

void setValueToTensor(   double * vector,
                          size_t dim_x,
                          size_t dim_y,
                          size_t dim_z,
                          double value, int x, int y, int z);

答案 4 :(得分:0)

double ***是指向指向double的指针的指针,而不是指向double的3维数组。要取消引用double foo[1][2][3],我们会做类似于此的事情:

a = *(foo + 1*sizeof(double))
b = *(a + 2*sizeof(double))
return *(b + 3*sizeof(double)

你好像假设它更像这样:

return *(foo + length(foo[0][0][0]) + length(foo[0][0][1]) + ... + length(foo[1][0][0])+ length(foo[1][0][1] + ... + 3*sizeof(double)

这不是C中的数组如何工作。首先,C不会跟踪所有子阵列的长度,因此无法在运行时进行计算。没有什么可以阻止你实现你自己的解除引用功能,只要你以某种方式跟踪子阵列长度,就可以将1-d数组视为具有任意数量的维度,但是你可以&#39; t使用标准[]运算符。

如果您希望能够将三维数组取消引用为foo[0][0][0],则需要按如下方式对其进行分配(对所需的数组长度进行一些假设,并省略错误检查)清晰度):

double*** tensor = malloc(a*sizeof(double**);
for (unsigned i=0; i<a; ++i) {
    tensor[i] = malloc(b * sizeof(double*));
    for (unsigned j=0; i<b; ++j)
        tensor[i][j] = malloc(c * sizeof(double));
}