1

My c skills are very rusty, so I apologize if this is a dumb question, but I could not even think were to look for the answer to this simple question. This code compiles without any warnings:

#include <ruby.h>

int run_script( int argc, char *argv[] )  {
  ruby_sysinit(&argc,  &argv);
}

But when I compile this code, I get the following warning:

#include <ruby.h>

int run_script( char * parameters )  {
    int argc=0;
    char *argv[1];
    ruby_sysinit(&argc,  &argv);
}

run_script_3.c: In function 'run_script':
run_script_3.c:7: warning: passing argument 2 of 'ruby_sysinit' from incompatible pointer type

it seems like i am passing the same pointer type in both cases.

evnu
  • 6,450
  • 2
  • 27
  • 38
nPn
  • 16,254
  • 9
  • 35
  • 58

2 Answers2

2

The problem is that an array in formal parameter declaration is equivalent to pointer. Declaration of

int run_script( int argc, char *argv[] )  { ... }

is equivalent to

int run_script( int argc, char **argv)  { ... }

because you can not send an array as parameter. You can send only a pointer and even if you put an array as actual parameter it is always converted to a pointer. Then if you put &argv you are getting address of this parameter, so it is an address in system stack where argv's value is stored.

On the other hand array in code is still an array, which is different type. In your case &argv is of type char *** inside the first version of run_script while it is of type char *(*)[1] in the second version. It looks like the same type, but it is not. In run time, there is even bigger difference, because your two invocations are sending two completely different values to ruby_sysinit.

Your second example:

int run_script( char * parameters )  {
    int argc=0;
    char *argv[1];
    ruby_sysinit(&argc,  &argv);
}

will probably cause segfault because opearator & applied on an array gives the pointer to the first element of the array. So the call ruby_sysinit(&argc, &argv); is sending the same values as ruby_sysinit(&argc, argv);, i.e. a value which points to char*, not to pointer to char* as expected by ruby_sysinit.

Marian
  • 7,402
  • 2
  • 22
  • 34
0

The signature of ruby_sysinit is as follows (correct me if I picked the wrong ruby version, I don't have the header file on my system):

void ruby_sysinit(int *argc, char ***argv);

This means that the following compiles:

extern void ruby_sysinit(int *argc, char ***argv);

int run_script(char * params)  {
    int argc = 0;
    char **argv;
    ruby_sysinit(&argc, &argv);
}

Now, when you declare char *argv[1], you tell the compiler that this is an array with one element. This is not the same as char **argv.

EDIT: you might find this question on SO and this article (as linked in the other question) useful.

Community
  • 1
  • 1
evnu
  • 6,450
  • 2
  • 27
  • 38