在C中访问2D数组[x] [y]作为1D数组[z]

时间:2017-04-15 16:02:12

标签: c arrays pointers

我最近开始编写C代码块作为我大学编程课程的一部分(所以你可以自由地假设我是一个完全白痴)。我正在尝试编写一个将2D数组的数据写入文件的函数,但是我遇到了困难。我在main中声明了数组,我将其x和y维度保存为#define s,我想像我这样调用function();

include "function.h"
#define /* x_res, y_res */
int main(){
  static unsigned char pic[x_res][y_res];
  /* do some operations on pic*/
  function(pic,x_res,y_res);
}

函数本身保存在头文件中,旨在包含在我的主.c文件的最顶层。它是这样的;

void function(unsigned char arry,int x_res,int y_res){
    /* some calculations, declaring file pointer with fopen() */
    for(int i=0;i<y_res;i++){
        for(int j=0;j<x_res;j++){
            fprintf(f,"%c",arry[i][j]);
        }
    }
}

我遇到行fprintf(f,"%c",arry[i][j]);中的错误,说“下标值既不是数组也不是指针也不是向量”,这是假的,因为我知道arry是一个数组。此外,如果我尝试用fprintf(f,"%c",arry[i*j+j]);之类的东西替换所述行,则错误消失,但文件输出是乱码(我假设我只打印{{的第一维元素的地址1}})。

然后问题;为什么不能像他们的1D对应物一样访问2D数组,我该如何解决这个问题呢?我想,arry会给出

的输出
int array[][]={{0,1},{2,3}};

,但事实并非如此 - 它会打印0,2,然后打印两个内存地址。

我已经尝试声明我的函数接受array[0] -> 0 array[1] -> 1 array[2] -> 2 array[3] -> 3 的参数,工作但不是我希望函数工作的方式。

我看过其他一些在线示例,但似乎很少有人遇到过类似的问题。我尝试了this question的一些答案,但事情再次起作用。例如,使用void function(unsigned char arry[*value of x_res*][*value of y_res*],x_res,y_res)可以将数组作为2D(void function(unsigned char **arry,x_res,y_res))进行访问,但同样,与上面的示例一样,大多数值(所有不在第一列中的值)都是垃圾。< / p>

1 个答案:

答案 0 :(得分:1)

在C99及更高版本中,可能有VLA

 void function(int x_res, int y_res, int char[][y_res])
 {
     for(int i=0;i<x_res;i++)
     {
          for(int j=0;j<y_res;j++)
          {
              fprintf(f,"%c",arry[i][j]);
          }
     }
 }

问题是在C11中支持VLA的实现是可选的(即,不需要C11编译器来支持它们)。并且C90(1990年的ISO C标准)肯定不支持VLA。

声明的数组在内存中是连续的,因此可以像平面1D数组一样对待。例如;

 void function2(int x_res, int y_res, unsigned char *arr)
 {
     for(int i=0;i<x_res;i++)
     {
          for(int j=0;j<y_res;j++)
          {
              fprintf(f,"%c",arr[i*y_res + j]);
          }
     }
 }

 int main()
 {
      unsigned char x[10][20];
      unsigned char y[10*20];
      unsigned char *z = malloc(10*20*sizeof(*z));

      /*  initialise elements x, y, and z  */

      function2(10,20, (unsigned char *)x);
      function2(10,20, &x[0][0]);

      function2(10,20, y);
      function2(10,20, z);
 }

首次调用function()时需要进行类型转换,因为unsigned char的2D数组无法隐式转换为unsigned char *。但是,x的地址和x[0][0]的地址具有相同的值,即使它们具有不同的类型。

使用这种技术的问题是,在编译时不会检查传递的维度(function2()的前两个参数)。例如;

   int xx[5][6];

   function2(10, 20, (unsigned char *)xx);   /* danger, Will Robinson!! */
   function2(10, 20, &xx[0][0]);             /*  danger, danger!! */

将编译,但由于xx的维度小于前两个参数告诉function2()预期,将导致function2()对两个调用都有未定义的行为。