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

wef*_*fa3 42 c++ declaration function variadic-functions

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

int f(int n, ...);
Run Code Online (Sandbox Code Playgroud)

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

int f(int n...); // the comma has been omitted
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

kfs*_*one 36

根据C++标准§8.3.5.4(当前草案):

在语法正确且"......"不是抽象声明者的一部分的地方,",......"与"......"同义.

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

  • ......而且,在我看来,为了清楚起见.`int n ...`看起来应该与参数包扩展有关.或者,至少看起来```与`n`有关. (11认同)
  • @Pharap允许遗漏逗号的可能目的是什么? (2认同)

Bar*_*rry 29

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

int f(int n, ...);
int f(int n ...);
Run Code Online (Sandbox Code Playgroud)

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

template <class... T> void f(T...); // function template with parameter pack
template <class T> void f(T...);    // variadic function
Run Code Online (Sandbox Code Playgroud)

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


hls*_*lon 15

随着int f(int n, ...);int f(int n...);,你可以看到,无论是, ......具有相同的含义.逗号是可选的.

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


JDł*_*osz 6

正如我记得的那样,C++确实定义了可变参数函数signatues.后来,快速发展的C语言(从K&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
,argument-declaration
       argument-declaration

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

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

随着C的正确标准化工作的进展,C++编译器也开始接受C版本,以便轻松使用C标准头文件.

为什么C设计者在将椭圆作为假参数占位符意味着不太合理的语法角色时添加逗号?我从未发现过.