2014-02-07 71 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*