2011-08-17 58 views
12

只是用C++來玩一下。我真正想要做的是能夠使用爲數組或指針參數定義的默認值設置函數。爲了簡單起見,我們只需使用一個數組。像這樣:數組參數的默認值

void experimentA(char a[3] = {'a', 'b', 'c'});

編譯器(LLVM GCC 4.2 GNU99)抱怨 「預期表達」。這很不靈敏,但我被同事告知,這是因爲我試圖分配的「值」是靜態分配的,而我試圖將其分配給(a[3])的變量是自動分配的。

但我不能完全肯定,如果是這樣的話,因爲我能做到這一點:

void experimentB(char a[3] = "abc");

,編譯器只是警告我說,字符串文本爲char *轉換已過時。

我不明白「abc」如何與{'a','b','c'}有根本的不同,以便引起這種差異。任何有識之士都非常感謝!

+0

記住 「ABC」 是真{ 'A', 'B', 'C', '\ 0'}這將適合一個大小爲4的數組。 –

+1

@Doug:當使用字符串字面值初始化一個char數組時,不必爲空終止符設置空格。如果程序員指定了明確的長度,他應該知道他在做什麼。 –

回答

6

你的同事是錯的或者你被誤解了。

理解的第一個線索是,您不能在C或C++中將數組作爲函數參數。原因是歷史的。因此,當您編寫void experimentA(char a[3] ...)時,編譯器會自動將其轉換爲指針,即void experimentA(char* a ...)。所以真正的問題是爲什麼​​是一個合適的默認值,而不是{ 'a', 'b', 'c' }。原因是編譯器解釋,​​是一個表達式,並且{ 'a', 'b', 'c' }不是(它是一個初始化程序)。在C++中有一些地方可以使用一個初始化程序,有些地方你不能使用。參數的默認值恰好是您不能使用的地方之一。

+0

非常好。這就說得通了。太糟糕了,我只能選擇其中一個答案作爲'答案'。 –

1

​​是一個表達式,{'a', 'b', 'c'}是一個靜態初始化器。後者只能在變量聲明中使用。由於默認值的參數默認值有不同的語法規則,不允許靜態初始值設定項。

在C++ 0x中允許使用靜態初始值設定項時會發生一些重大更改,但我不確定它是如何影響相關案例的。

4

當您使用字符串文字「abc」時,它由編譯器在內存中的某處分配,並且指向其第一個字符的指針用作默認值。所以對於編譯器來說代碼就是這樣的:void experimentA(char a[3] = 0x12345678);

對於第二種情況,數組文字不是由編譯器作爲字符串分配的(我認爲這是語言中的一些不一致)。

2

​​是表達式。當它用於初始化一個類型爲array of char的變量時,它恰好表現出與所有其他表達式不同的特殊行爲。

{'a','b','c'}不是一個表達式,而是一個初始化程序。它在變量定義中僅在語法上是允許的。在那裏,語法允許一個表達式或一個非表達式初始值設定項,但這並不代表初始值設定項可以在其他任何地方用作表達式。

+0

+1用於解釋初始值設定項的有效用例。謝謝,這清除了我剩下的幾個小問題。 –

1

默認參數必須有效。

可以調用

F( 「ABC」)

但從未

F({ 'A', 'B', 'C'});

「abc」實際上是內存中的一個地址,{'a','b','c'}表示初始化一個數組或結構體/類。

0

一個簡單的方法是通過普通的舊函數重載。例如,下面模擬爲格式參數的默認參數值是char *類型:

static string to_string(time_point<system_clock> time) 
{ 
    return to_string(time, "%Y-%m-%d-%H-%M-%S"); 
} 

static string to_string(time_point<system_clock> time, const char* format) 
{ 
    time_t tt = system_clock::to_time_t(time); 

    char str[1024]; 
    if (std::strftime(str, sizeof(str), format, std::localtime(&tt))) 
     return string(str); 
    else return string(); 
}