在C ++中的可变参数函数声明中省略了逗号

时间:2016-02-29 19:32:30

标签: c++ function declaration variadic-functions

我习惯于声明像这样的可变函数:

int f(int n, ...);

阅读 C ++编程语言时,我发现书中的声明省略了逗号:

int f(int n...); // the comma has been omitted

看起来这个语法是特定于C ++的,因为当我尝试使用C编译器编译它时出现此错误:

  

test.c:1:12: error: expected ‘;’, ‘,’ or ‘)’ before ‘...’ token int f(int n...);

int f(int n, ...)int f(int n...之间有什么区别吗?

为什么这个语法添加了C ++?

4 个答案:

答案 0 :(得分:36)

根据C ++标准§8.3.5.4(current draft):

  

语法正确且“......”不属于的地方   一个抽象声明者,“,......”与“......”同义。

简而言之,在C ++中...(省略号)本身就是一个运算符,因此可以在没有逗号的情况下使用,但保留使用逗号以实现向后兼容。

答案 1 :(得分:29)

目前,这两个声明都具有相同的含义:

int f(int n, ...);
int f(int n ...);

这导致了以下两个声明既合法又具有截然不同的含义的问题:

template <class... T> void f(T...); // function template with parameter pack
template <class T> void f(T...);    // variadic function

一旦C ++ 11引入了可变参数模板,第二个声明更可能是程序员错误,而不是懒惰地省略逗号。因此,有人建议将后者从语言中删除(P0281),但显然是rejected

答案 2 :(得分:15)

使用int f(int n, ...);int f(int n...);, ... ...int printz(...);具有相同的含义。逗号是可选的。

但是这个C++int printz(,...);中有效,而(...)不是(至少有一个命名参数必须出现在省略号参数之前)。这就是为什么你可以只有{{1}},即使传递给这种函数的参数不可访问。

答案 3 :(得分:6)

正如我记得的那样,C ++确实定义了可变参数函数signatues。后来,快速发展的C语言(从K&amp; R到ANSI的旅程)引入了原型新式函数声明,它们也在函数名后面的parens中声明了参数。但是,有两个值得注意的差异:省略号之前的逗号,以及(void)的憎恶表示空参数列表的需要(以保持空白parens的向后兼容性为旧样式声明)。

查看我的档案,我发现 The C ++ Programming Language 原版“重印了1987年7月的更正”,显示:

argument-declaration-list:
arg-declaration-list opt
... opt <登记/>
arg-declaration-list:
arg-declaration-list
, 参数声明
参数声明

无形式接受现在可选的逗号。请注意,arg-declaration-list是逗号 - 分隔,并且不会挂出以在列表之后和下一个(不同)之前提供逗号。

这是写这个的最自然的方式。如果你想要一个逗号,你需要在第一个作品中明确, ...,作为两个不同的(可能是空格分隔的)标记。

随着C正在进行适当标准化的努力,C ++编译器也开始接受C版本,以便轻松使用C标准头文件。

为什么C设计师添加逗号时,它意味着省略号作为假参数占位符的语法角色不太合理?我从未发现过。