简体   繁体   中英

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). I'm trying to write a function that writes a 2D array's data to a file, but I'm having difficulties. 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;

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. 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]); saying that the "subscripted value is neither array nor pointer nor vector", which is false since I know that arry is an array. Furthermore, if I try to replace said line with something like 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 ).

The question, then; Why can't 2D arrays be accessed like their 1D counterparts, and how do I work around this? I would imagine that an 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.

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.

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.

In C99 and later, it is possible to have a 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). And VLAs are definitely not supported in C90 (the ISO C standard of 1990).

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 * . However, the address of x and the address of x[0][0] have the same value, even though they have different types.

A gotcha with this technique is that the dimensions passed (first two arguments of function2() ) are not checked at compile time. 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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