2014-02-07 62 views
1

我的c技能非常生疏,所以我很抱歉如果这是一个愚蠢的问题,但我甚至不能想到要寻找这个简单问题的答案。 此代码编译没有任何警告:在传递char * argv []和声明char * argv之间有什么不同?

#include <ruby.h> 

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

但是,当我编译这段代码,我得到以下警告:

#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 

好像我传递相同的指针类型在这两种情况下。

+0

只需确认:两种情况下的编译选项(警告级别等)相同? –

+0

是完全相同的命令行选项,只是不同的文件内容 – nPn

+0

什么是ruby_sysinit的原型? –

回答

0

ruby_sysinit签名如下(纠正我,如果我选错了红宝石版本,我没有我的系统上的头文件):

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

这意味着下面的编译:

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

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

现在,当您声明char *argv[1]时,您告诉编译器这是一个包含一个元素的数组。这与char **argv不一样。

编辑:你可能会发现this question on SOthis article (as linked in the other question)有用。

2

问题是,形式参数声明中的数组与指针等价。因为你不能发送一个数组作为参数的

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

声明等效于

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

。你只能发送一个指针,即使你把一个数组作为实际参数,它总是被转换为一个指针。那么如果你把&argv你得到这个参数的地址,所以它是系统栈中的一个地址,其中argv的值被存储。

另一方面,代码中的数组仍然是一个数组,它是不同的类型。在您的情况下,&argv的类型为char ***,在run_script的第一个版本中,而在第二个版本中的类型为char *(*)[1]。它看起来像是相同的类型,但它不是。在运行时,更大的差异,因为你的两个调用发送两个完全不同的值到ruby_sysinit

你的第二个例子:

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

很可能导致段错误,因为施加于阵列上opearator &给出的指针数组的第一个元素。因此,呼叫ruby_sysinit(&argc, &argv);正在发送与ruby_sysinit(&argc, argv);相同的值,即,指向char*的值,而不是如ruby_sysinit所预期的那样指向char*