2011-08-17 111 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(); 
}