我习惯于声明像这样的可变函数:
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 ++?
答案 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设计师添加逗号时,它意味着省略号作为假参数占位符的语法角色不太合理?我从未发现过。