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

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

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 ++?

根据C ++标准的第8.3.5.4节( 当前草案 ):

在句法正确的地方,“…”不是抽象声明的一部分,“,…”与“…”是同义的。

简而言之,在C ++中... (省略号)本身就是一个操作符,所以可以不用逗号来使用,但为了向后兼容,使用逗号是保留的。

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

 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引入了可变参数模板,第二种声明更可能是程序员错误,而不是懒惰地忽略逗号。 因此,有人build议从语言中删除后者( P0281 ),但显然被拒绝了 。

int f(int n, ...);int f(int n...); 正如你所看到的 ,两者, ......具有相同的含义。 逗号是可选的。

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

就像我记得的那样,C ++确实定义了可变函数签名。 后来,快速发展的C语言(从K&R到ANSI的旅程)引入了原型新型函数声明 ,该声明还在函数名称后面的parens中声明了参数。 但是,有两个显着的区别:椭圆之前的逗号和需要(void)的憎恶来表示一个空的参数列表(为了保留空的参数作为旧式声明的向后兼容性)。

通过我的档案查看,我发现C ++编程语言原版“1987年7月更正转载”显示:

参数声明列表:
arg-declaration-list opt ... opt

ARG-声明列表:
arg-declaration-list , 参数声明
参数声明

没有forms接受现在可选的逗号。 请注意,arg-declaration-list是逗号分隔的 ,这不会在列表之后和下一个(不同的)之前提供逗号。

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

随着C正确标准化的努力取得进展,C ++编译器也开始接受C版本,以便于使用C标准头文件。

为什么Cdevise师在隐含椭圆的语法angular色作为假参数占位符时添加了逗号? 我从来没有发现。