将1d缓冲区重新组织为2d数组

Re-Organize 1d buffer as a 2d array

本文关键字:2d 数组 新组织 1d 缓冲区      更新时间:2023-10-16

我有一个足够大的1d缓冲区(int buffer[100])。我需要重新组织与二维数组相同的内存。我要做的是将其类型转换为双指针(int ** p),然后将指针传递给alloc函数,该函数将进行重组。函数返回后,我需要语句p[2][2]工作。

这是代码:

#include <stdlib.h>
#include <stdio.h>
void alloc(int ** buf, int r, int c)
{
    int **temp;
    temp=buf;
    for(int i=0;i<r;i++)
        buf[i]=*(temp+i*c);
}
void main()
{
    int buffer[100];
    int **p=(int **)buffer;
    alloc(p, 4, 4);
    p[2][2]=10;
    printf("%d", p[2][2]);
}

上面的代码编译成功,但是当我运行代码时,我在执行语句

时得到访问冲突。
p[2][2]=10;
我不明白问题出在哪里。是否有一个问题与分配函数?还是问题出在别的地方?

让我们检查一下您的代码,以了解为什么它不起作用。

让我们用一个更短的缓冲区来理解你在做什么。

假设你有:

int buffer[9];

,你想把它当作一个3x3的2D数组。已使用内存缓冲区:

buffer
|
v
+---+---+---+---+---+---+---+---+---+
|   |   |   |   |   |   |   |   |   |
+---+---+---+---+---+---+---+---+---+

您想要创建这样一个int** p:

p[0]        p[1]        [p2]
|           |           |
v           v           v
+---+---+---+---+---+---+---+---+---+
|   |   |   |   |   |   |   |   |   |
+---+---+---+---+---+---+---+---+---+

为了完成这一点,您必须分配内存来存储p[0], p[1]p[2]。这意味着,您需要:

int** p = new int*[3];
p[0] = buffer;
p[1] = buffer + 3;
p[2] = buffer + 6;

现在,p以及p[0], p[1], p[2]都指向有效地址。您可以使用语法p[m][n]

在我们的代码中,您只是指定p指向与buffer相同的位置,并使用语句

buf[i]=*(temp+i*c);

你只是使用buffer持有的内存作为int*的占位符,这不仅践踏了buffer中的数据,而且使指针的值不可预测。

这是一个工作程序。

#include <stdio.h>
int main()
{
   int buffer[100];
   int rows = 4;
   int cols = 10;
   int **p = new int*[rows];
   for ( int i = 0; i < rows; ++i )
   {
      p[i] = buffer + i*cols;
      printf("%pn", p[i]);
      for ( int j = 0; j < cols; ++j )
      {
         p[i][j] = i*2 + j*3;
      }
   }
   printf("n");
   for ( int i = 0; i < rows; ++i )
   {
      for ( int j = 0; j < cols; ++j )
      {
         printf("%d ", p[i][j]);
      }
      printf("n");
   }
}

如果使用C语言,可以简单地将数组强制转换为正确的类型:

void main() {
    int width = 10, height = 10;
    int buffer[width*height];
    int (*p)[width] = (int (*)[width])buffer;
    p[2][2]=10;
    printf("%d", p[2][2]);
}

或者直接使用二维数组:

void main() {
    int width = 10, height = 10;
    int buffer[width][height];
    buffer[2][2]=10;
    printf("%d", buffer[2][2]);
}

这是有效的,因为C中的2D数组是数组的数组。因此,2D数组是一个由十个数组组成的数组,每个数组有十个元素,它们都按顺序存储在内存中。类型int (*)[width]表示指向这些行数组之一的指针的类型。因此,当您执行p[2]时,您调用指针算术,在解引用指针之前将行数组的大小增加两倍。这(间接地)导致第三行数组的第一个元素的int*,您可以再次调用相同的指针算法来选择2D数组中的正确元素。

这在c++中不能无缝地工作,因为数组类型在c++中必须有一个编译时大小。C在这方面更加灵活,允许您轻松地将任意大小的2D数组传递给函数:

void foo(int width, int height, int (*image)[width]);
void main() {
    int width = 10, height = 10;
    int buffer[width][height];
    foo(width, height, buffer);
}
#include <stdio.h>
int main(){
    int buffer[100];
    int (*p)[4]=(int (*)[4])buffer;//int p[25][4]
    p[2][2]=10;
    printf("%dn", p[2][2]);
    printf("%dn", buffer[4*2+2]);//10
    return 0;
}

不能将 1D数组转换为2D数组。实际上,每一个多维数组都只是细胞的一维/线性集合,编程语言制造了多维的错觉。你也可以创建同样的错觉,即抽象一个1D数组,使其看起来像2D(任意更高维度)

你可以这样做:

#define ROW 10
#define COL 10
int arr[size]={1,2...}; //I am making it global, you can declare it anywhere
int& getValueFrom2DArray(int row,int col) // return type is a reference, so that you can assign
{
 if( row>= ROW || col >= COL)
  return -1; //treating -1 as sentinel value
 return array[ row*COL + col]; // convert 2D co-ordinates into 1D position
}
int main() //return type of main should be int, not void
{
   getValueFrom2DArray(2,2) = 10;
   cout<< getValueFrom2DArray(2,2)<<endl;
   return 0;
}