0

For below code how do I pass char[][] as char** parameter?

#include <stdio.h>
#include <string.h>


void fn(int argc,char** argv)
{
 int i=0;   
 printf("argc : %d\n",argc);
 for(i=0;i<argc;i++)
     printf("%s\n",argv[i]);
}

int main()
{
char var3[3][10]={"arg1","argument2","arg3"};
char var4[4][10]={"One","Two","Three","Four"};

fn(3,&var3);
fn(4,&var4);


return 0;
}

Getting below error:

$ gcc -Wall anyNumberOfParameters.c -o anyNumberOfParameters.exe
anyNumberOfParameters.c: In function ‘main’:
anyNumberOfParameters.c:18:1: warning: passing argument 2 of ‘fn’ from incompatible pointer type [enabled by default]
 fn(3,&var3);
 ^
anyNumberOfParameters.c:5:6: note: expected ‘char **’ but argument is of type ‘char (*)[3][10]’
 void fn(int argc,char** argv)
      ^
anyNumberOfParameters.c:19:1: warning: passing argument 2 of ‘fn’ from incompatible pointer type [enabled by default]
 fn(4,&var4);
 ^
anyNumberOfParameters.c:5:6: note: expected ‘char **’ but argument is of type ‘char (*)[4][10]’
 void fn(int argc,char** argv)
      ^

If I change my code in main() as:

char* var3[3]={"arg1","argument2","arg3"};
char* var4[4]={"One","Two","Three","Four"};

fn(3,var3);
fn(4,var4);

It works fine, but I want to know how do I pass char[][] as parameter.

char var[3][10]={"One","Two","Three"};
printf("%s",var[1]);

it does print : Two So if I pass var to char** ; won't it be equivalent to two dimentional array's address?

I mean for a function fn(char*) we do pass as:

char name[20]="Thomas";
fn(name);

char** is making me confused

Gaurav K
  • 2,698
  • 6
  • 33
  • 60
  • 2
    The suggested duplicate is a C++ question; this is a C question – M.M May 25 '14 at 22:20
  • 2
    Hint: print the size of `var3` and `var4`. Another hint: in-memory layout of `char**` and `char[][]` are different. – user703016 May 25 '14 at 23:23
  • I do not know why negative vote? It is a valid question and I received good explanation.. It would be helpful for any beginner.. :( – Gaurav K May 26 '14 at 03:17

2 Answers2

8

If you dereference a char **, you should get a pointer to char. There are no pointers in a char[3][10]. They're just not interchangeable.

It works for a one-dimensional char * array because the array name implicitly converts to a pointer to the first element in this context, and if you dereference a char * you get a char, and that's exactly what your one-dimensional char array contains.

The line of thinking that "if it works for a one-dimensional array, shouldn't it work for a two-dimensional array?" is just invalid, here.

To make what you want to do work, you'd have to create char * arrays, like so:

#include <stdio.h>

void fn(int argc, char ** argv) {
    printf("argc : %d\n", argc);
    for (int i = 0; i < argc; ++i) {
        printf("%s\n", argv[i]);
    }
}

int main(void) {
    char * var3[3] = { "arg1", "argument2", "arg3" };
    char * var4[4] = { "One", "Two", "Three", "Four" };

    fn(3, var3);
    fn(4, var4);

    return 0;
}

which outputs:

paul@local:~/src/c/scratch$ ./carr
argc : 3
arg1
argument2
arg3
argc : 4
One
Two
Three
Four
paul@local:~/src/c/scratch$ 

An alternative is to declare your function as accepting an array of (effectively a pointer to) 10-element arrays of char, like so:

#include <stdio.h>

void fn(int argc, char argv[][10]) {
    printf("argc : %d\n", argc);
    for (int i = 0; i < argc; ++i) {
        printf("%s\n", argv[i]);
    }
}

int main(void) {
    char var3[3][10] = { "arg1", "argument2", "arg3" };
    char var4[4][10] = { "arg1", "argument2", "arg3", "arg4" };

    fn(3, var3);
    fn(4, var4);

    return 0;
}

but this obviously requires hard-coding the sizes of all dimensions except the leftmost, which is usually less desirable and flexible. char argv[][10] in the parameter list here is another way of writing char (*argv)[10], i.e. declaring argv as a pointer to array of char of size 10.

Crowman
  • 22,866
  • 5
  • 38
  • 54
1

A type** is by definition a pointer to a pointer, or an array of pointers.

When used in a function declaration, type[][] is inteligible with type** as in:

int main(int argc, char argv[][]) { ...

But it is not when declaring variables. When you do this:

char var[a][b] = { ... }

This is a matrix of char and there are no pointers envolved here. The compiler pretty much handles this as a straight forward array of char var[a*b] and when you access var[1][2] it internally does var[1*b+2]. It is not really an array of strings, and its utilization is only possible because the compiler knows the value of b when compiling this function, as the variable was declared there.

In order to pass as char**, var must be an array of pointers. A list containing pointers of char*.

When you do this:

char *var[a] { ... }

Now you are telling the compiler your intention. var is no longer a matrix of char, it is truly a list of pointers char*.

Havenard
  • 23,249
  • 4
  • 31
  • 59