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

时间:2014-05-31 05:18:00

标签: c++ c arrays pointers

我得到足够大小的1d缓冲区(int buffer[100])。我需要重新组织与2d数组相同的内存。我想要做的是将它转换为双指针(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;

我无法理解问题所在。 alloc函数有问题吗?或者是其他问题?

4 个答案:

答案 0 :(得分:6)

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

让我们使用较短的缓冲区来了解你在做什么。

我们说你有:

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("%p\n", 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");
   }
}

答案 1 :(得分: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;
}

答案 2 :(得分:0)

如果您使用的是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]);
}

或直接使用2D数组:

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);
}

答案 3 :(得分:0)

#include <stdio.h>

int main(){
    int buffer[100];
    int (*p)[4]=(int (*)[4])buffer;//int p[25][4]

    p[2][2]=10;
    printf("%d\n", p[2][2]);
    printf("%d\n", buffer[4*2+2]);//10
    return 0;
}