【问题标题】:Getting inner values of a pointer to a three-dimensional int in C在C中获取指向三维int的指针的内部值
【发布时间】:2021-05-26 14:21:27
【问题描述】:

所以这是我第一次在 C 中使用多维数组。我有一个 3D 整数数组正在填充,我想检查以确保值正常,但是数组填充后我遇到了一些问题。 一些类似的代码来解释这种情况:

int a = 10;
int b = 20;
int c = 30;
int* valuesPtr;
valuesPtr = (int*) malloc(a * b * c * sizeof(int));
functionThatFillsValues(valuesPtr); // this function expects a *int, and works.

这里一切正常。然后,我打印出这样的值:

printf("0,0,0: %d\n", *valuesPtr);

这会成功打印 [0][0][0] 处的值。做以下工作:

printf("0,0,1?: %d\n", *(valuesPtr+1));

现在,我从https://www.geeksforgeeks.org/pointer-array-array-pointer/ 了解到,有几种方法可以从该指针指向的位置获取值。 以下工作:printf("0,0,0: %d\n", valuesPtr[0]); 但只要我尝试更进一步,它就会中断。以下都不起作用:

printf("0,0,0: %d\n", valuesPtr[0][0];
printf("0,0,0: %d\n", valuesPtr[0][0][0];
printf("0,1,0: %d\n", valuesPtr[0][1];
printf("0,0,1: %d\n", valuesPtr[0][0][1];
printf("%d\n", *(*(valuesPtr+1)+1));
printf("%d\n", *(*(*(valuesPtr+1)+1)+1));

[] 得到错误“下标值既不是数组也不是指针”,而 *() 尝试得到错误“'unary *' (have 'int') 的类型参数无效”我猜因为在这两种情况下,它都将 valuesPtr[0] 和 *(valuesPtr) 解析为 int,然后不再继续。我猜问题是 valuesPtr 被声明为 *int,所以它认为它只是一个指向 int 的指针。我怎样才能理解它是一个指向 3D 数组的指针,或者通过获取指向内部 2D 或 1D 数组的指针,或者只是让它理解我可以使用 [][][] 表示法?

这样的东西会在正确的位置上寻找吗?

printf("i,j,k: %d", *(valuesPtr+(i*(c*b))+(j*(c))+k)

【问题讨论】:

  • 您正在分配一个平面数组,您只能使用[]* 语法取消引用一次。 Correctly allocating multi-dimensional arrays 的答案可能有你想要的。
  • @m-oehm 不幸的是,该函数不能接受除 *int 之外的任何内容 - 这不是我有权更改的内容。所以它必须是一个平面阵列。但是知道它是一个平面数组,我在问题末尾的想法应该是寻找正确的位置,是吗?
  • @SpaceMouse - 这个想法是正确的,但数学是错误的。由于您实际上使用的是平面数组,因此您必须根据原始分配计算其他维度。像这样: printf("%d ", *(valuesPtr + (i*20*30)+(j*30)+(k)));
  • 如果您将平面数组别名为连续的多维数组,您仍然可以使用该答案中使用的技术:int (*m)[20][10] = (int (*)[20][10]) valuesPtr; 现在您可以使用m[k][j][i] 语法对数组元素进行索引。 See an example here.

标签: arrays c pointers


【解决方案1】:

您可以做两种不同的事情。

选项#1 是简单地使用线性偏移来访问您的元素。为此,您必须从三元组计算单个偏移量。让我给你举个例子:

printf("2, 3, 4: %d\n", valuesPtr[(2 * b + 3) * c + 4]);

这有点麻烦,但这是传统的做事方式,而且很管用。

如果您使用的是 C99 或更高版本,另一种方法是使用所谓的可变修改类型。请注意,这需要支持 VLA,自 C11 以来这是可选的,因此某些实现(尤其是 MSVC)可能不支持它们。

如果您手动声明数组,则为int arr[a][b][c];。由于数组到指针的衰减规则,当在表达式中使用时,这将成为 int (*) [b][c] — 即指向 b 数组 c 元素的数组的指针。因此,您可以将指针类型声明为该类型:

int (* valuesPtr) [b][c] = malloc(sizeof *valuesPtr * a);
// note that, since each element is already an array of [b][c], you only
// need to multiply by a to get the final size
printf("0, 0, 0: %d\n", valuesPtr[0][0][0]);
printf("1, 0, 0: %d\n", valuesPtr[1][0][0]);
printf("0, 1, 0: %d\n", valuesPtr[0][1][0]);
printf("0, 0, 1: %d\n", valuesPtr[0][0][1]);

【讨论】:

    【解决方案2】:

    如果我正确理解您的问题,您正在使用 3d 数据集。但是,您必须使用映射到 3D 数组的 1D 数组。也许以下内容会有所帮助:

    您可能会考虑构建 1D 数组和 3D 数组的(免费)联合,以便您可以以更方便的方式引用数据。也就是说,您可以使用三重索引填充 3D 数组,但对于 1D 目的,您可以定位线性数组中的第一个整数。

    由于数组的大小相同,联合将不包含任何额外内容,并且以任何一种方式引用您的数据都不会花费太多。一个简单的例子:

    // FreeUnion.c
    
    #include <stdio.h>
    
    #define     a   10      // defines for the sizing below
    #define     b   20
    #define     c   30
    
    union blob {
        int a3d[a][b][c];   // a 3d array
        int a1d[a*b*c];     // a 1d array
    } arrun;
    
    void main(void) {
        arrun.a1d[0] = 0;
        arrun.a1d[1] = 1;
        arrun.a1d[2] = 2;
    
        printf("one: %i\n", arrun.a1d[1]);
        printf("triplet 0: %i, %i, %i \n", arrun.a3d[0][0][0],
                         arrun.a3d[0][0][1], arrun.a3d[0][0][2]);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-07
      • 1970-01-01
      • 1970-01-01
      • 2017-06-19
      • 1970-01-01
      相关资源
      最近更新 更多