简体   繁体   English

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

[英]Access a 2D array[x][y] as a 1D array[z] in C

I recently started writing chunks of C code as part of my university's programming lessons (so you can freely assume that I am a complete idiot). 最近,作为我大学编程课程的一部分,我开始编写C代码块(因此您可以自由地假设我是一个完整的白痴)。 I'm trying to write a function that writes a 2D array's data to a file, but I'm having difficulties. 我正在尝试编写一个将2D数组的数据写入文件的函数,但是遇到了困难。 I declare the array in main, I have its x and y dimensions saved as #define s, and I want to call my function() like so; 我在main中声明该数组,将其x和y维保存为#define ,我想这样调用我的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);
}

The function itself is saved in a header file and is intended to be included at the very top of my main .c file. 该函数本身保存在头文件中,并打算包含在我的主.c文件的最顶部。 It goes something like this; 它是这样的:

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

I'm greeted with an error in the line fprintf(f,"%c",arry[i][j]); 我在行fprintf(f,"%c",arry[i][j]);遇到了一个错误fprintf(f,"%c",arry[i][j]); saying that the "subscripted value is neither array nor pointer nor vector", which is false since I know that arry is an array. 说“下标值既不是数组也不是指针也不是向量”,这是错误的,因为我知道arry是数组。 Furthermore, if I try to replace said line with something like fprintf(f,"%c",arry[i*j+j]); 此外,如果我尝试将上述行替换为fprintf(f,"%c",arry[i*j+j]); , the error goes away, but the file output is gibberish (I'm assuming I'm only printing the addresses of the first-dimension elements of arry ). ,错误消失了,但是文件输出却变得乱七八糟(我假设我只打印arry的第一维元素的地址)。

The question, then; 那么,这个问题; Why can't 2D arrays be accessed like their 1D counterparts, and how do I work around this? 为什么不能像2D数组那样访问2D数组,我该如何解决? I would imagine that an int array[][]={{0,1},{2,3}}; 我会想象一个int array[][]={{0,1},{2,3}}; would give an output of 将给出一个输出

array[0] -> 0
array[1] -> 1
array[2] -> 2
array[3] -> 3

, but this is not the case -- it prints 0, 2, and then two memory addresses. ,但事实并非如此-它先输出0、2,然后输出两个内存地址。

I've tried declaring my function to accept arguments as void function(unsigned char arry[*value of x_res*][*value of y_res*],x_res,y_res) , which works but is not how I would like the function to work. 我试过声明我的函数接受参数作为void function(unsigned char arry[*value of x_res*][*value of y_res*],x_res,y_res) ,该方法有效,但我不希望该函数起作用。

I've looked at some other online examples but it seems few people have had a similar problem. 我看过其他一些在线示例,但似乎很少有人遇到过类似的问题。 I tried some answers from this question but again things do not work. 我尝试过从这个问题中得到一些答案,但是事情还是不起作用。 For example, using void function(unsigned char **arry,x_res,y_res) works with accessing the array as 2D ( arry[i][j] ), but again, like with the example above, most values (all that aren't in the first column) are trash. 例如,使用void function(unsigned char **arry,x_res,y_res)可以将数组作为2D( arry[i][j] )进行访问,但是与上面的示例一样,大多数值(都不是'第一列中的t)是垃圾。

In C99 and later, it is possible to have a VLA 在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]);
          }
     }
 }

The problem is that support of an implementation for VLAs was made optional in C11 (ie a C11 compiler is not required to support them). 问题是在C11中对VLA的实现的支持是可选的(即,不需要C11编译器来支持它们)。 And VLAs are definitely not supported in C90 (the ISO C standard of 1990). 而且C90(1990年的ISO C标准)绝对不支持VLA。

An declared array is contiguous in memory, so can be treated like a flat 1D array. 声明的数组在内存中是连续的,因此可以将其视为平面一维数组。 For example; 例如;

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

The type conversion in the first call of function() is needed since a 2D array of unsigned char cannot be implicitly converted to a unsigned char * . 由于无法将unsigned char的2D数组隐式转换为unsigned char *因此需要在function()的第一次调用中进行类型转换。 However, the address of x and the address of x[0][0] have the same value, even though they have different types. 但是, x的地址和x[0][0]的地址即使具有不同的类型也具有相同的值。

A gotcha with this technique is that the dimensions passed (first two arguments of function2() ) are not checked at compile time. 使用此技术的一个陷阱是,在编译时不检查传递的尺寸( function2()前两个参数function2() For example; 例如;

   int xx[5][6];

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

will compile but, since the dimensions of xx are less than the first two arguments tell function2() to expect, will cause function2() to have undefined behaviour for both calls. 将会编译,但是由于xx的尺寸小于前两个参数告诉function2()的期望,将导致function2()的两个调用都具有未定义的行为。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM