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

Comma omitted in variadic function declaration in C++

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

int f(int n, ...);

在阅读The C++ Programming Language时发现书中的声明省略了逗号:

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

int f(int n, ...);int f(int n...);一样,可以see, ......具有相同的含义。逗号是可选的。

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

根据 C++ 标准的第 8.3.5.4 节 (current draft):

Where syntactically correct and where “...” is not part of an abstract-declarator, “, ...” is synonymous with “...”.

简而言之,在 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 引入可变参数模板,第二个声明更有可能是程序员错误,而不是懒惰地省略逗号。因此,有人提议将后者从语言中删除 (P0281), but it was apparently

我记得当时,C++ 确实如您所记定义了可变参数函数符号。后来,快速发展的 C 语言(从 K&R 到 ANSI 的旅程)引入了 prototypesnew-style function declarations ,它们也在括号内声明了参数在函数名称之后。但是,有两个显着的区别:省略号前的逗号,以及需要 (void) 的可憎性来指示空参数列表(以保持空括号的向后兼容性作为 旧样式声明)。

翻阅我的档案,我发现 The C++ Programming Language 原版 "reprinted with corrections July 1987" 显示:

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

arg-declaration-list:
arg-declaration-list
, argument-declaration
参数声明

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

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

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

为什么 C 语言的设计者要添加逗号,因为它暗示省略号作为假参数占位符的语法作用不太合理?我一直没发现。