简体   繁体   中英

Passing 2D arrays in C like argv of main

I am learning passing 2D arrays to functions in C and learned that I can receive 2D array in the function as following:

  1. void test(char a[5][10])
  2. void test(char (*a)[10])

Above declarations work for me but looking on **argv parameter of function main I thought of changing my function to void test(char **a) . But this does not work correctly. I do not understand why. Please explain.

Here is my code

#include<stdio.h>

int main(int argc, char **argv){
    char multi[5][10] = {
                         {'0','0','2','3','4','5','6','7','1','9'},
                         {'a','b','c','d','e','f','g','h','i','j'},
                         {'A','B','C','D','E','F','G','H','I','J'},
                         {'9','8','7','6','5','4','3','2','1','0'}, 
                         {'J','I','H','G','F','E','D','C','B','A'}
                        };
    test(multi);
    return 0;
}

void test(char (*a)[10]) // void test(char **a) does not work
{
    printf("\n a[2][1] is: %d",*(*(a + 2)+1));
}

An array name when passed to a function will decay to the value of the address of its first element, and its type will be a pointer to that element type. Since the type of multi[0] is a char[10] , then multi will decay pointer to char[10] .

main() receives an array of pointers to char in its second parameter, which is why argv can be char **argv or char *argv[] .

For multidimensional arrays, rows are stored in continuous memory locations. That's why we need to pass the number of columns, ie, to calculate the number of items to jump over to get to a specific row.

In case of pointer to pointers, rows are stored in arbitrary memory locations. You cannot find the location of a row given the pointer to the first row and an index. In this case, you need as much pointers as you have rows.

In short, the two versions of your function arguments assume different memory layouts and as such, they are incompatible.

Array in C is in essence one dimensional. When passing multi-dimensional array you should pass every dimension size except for the first one as constant integer. And the array is in passed as a pointer, not an array. Here is an alternative: Passing one dimensional or multi-dimensional pointer, along with demension sizes. For example: void test(char *a, int row, int column); and the index is: column * i + j; or: void test(char **a, int row, int column);

char (*a)[10] is a pointer to an array of characters. The operation (a+1) will increment the value of a by 10 bytes.

char **a is a double pointer. In this case, the operation (a+1) will increment the value of a by 4 bytes. Hence the below statement would result in erroneous behaviour.

printf("\\na[2][1] is: %d",*(*(a + 2)+1));

This is not a formal explanation but that's how I understand it: Arrays are actually stored linear in memory. For example, you define a 10x10 array and do b=a[4][5] , system will go to find the 4*10+5=45 th element in memory. That's why you cannot pass **a and access it as a 2D-array. It's a pointer without dimension information. With a[4][5] , the program will go to find the 4*(number of columns)+5 th element. Since it doesn't know how many elements there is in a row, it cannot do that.

You can always do something like this

#include<stdio.h>
#include<stdlib.h>
void test(char **a);
int main(int argc, char **argv){
    char **multi = (char**) malloc (5*sizeof(char*));
    char a[5][10] = {{'0','0','2','3','4','5','6','7','1','9'}, {'a','b','c','d','e','f','g','h','i','j'}, {'A','B','C','D','E','F','G','H','I','J'}, {'9','8','7','6','5','4','3','2','1','0'}, {'J','I','H','G','F','E','D','C','B','A'}};
    int i,j;
    for(i=0;i<5;i++)
    {
        multi[i] = (char*) malloc (10*sizeof(char));
    }
    for(i = 0;i<5;i++) 
    {
        for(j = 0; j < 10 ;j++)
        {
            multi[i][j] = a[i][j];

        }
    }
    test(multi);
    return 0;
}

void test(char **a) // void test(char **a) does not work
{
    printf("\n a[2][1] is: %c\n",*(*(a + 2)+1));
}

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