也许我不是来自这个星球,但在我看来,以下应该是一个语法错误:

int a[] = {1,2,}; //extra comma in the end

但事实并非如此。当这段代码在Visual Studio上编译时,我很惊讶,但我已经学会了不相信MSVC编译器,就c++规则而言,所以我检查了标准,它也是标准允许的。如果你不相信的话,语法规则可以参考8.5.1。

Why is this allowed? This may be a stupid useless question but I want you to understand why I am asking. If it were a sub-case of a general grammar rule, I would understand - they decided not to make the general grammar any more difficult just to disallow a redundant comma at the end of an initializer list. But no, the additional comma is explicitly allowed. For example, it isn't allowed to have a redundant comma in the end of a function-call argument list (when the function takes ...), which is normal.

那么,有什么特别的原因,这个多余的逗号是明确允许的吗?


当前回答

它使代码编辑变得容易得多。 我比较editinc c/c++数组元素与编辑json文档-如果你忘记删除最后一个逗号,json将不会解析。(是的,我知道JSON不能手动编辑)

其他回答

像许多东西一样,数组初始化器中的尾随逗号是c++从C继承的东西之一(并且必须永远支持)。在《Deep C secrets》一书中提到了与此完全不同的观点。

在一个有多个“逗号悖论”的例子之后:

char *available_resources[] = {
"color monitor"           ,
"big disk"                ,
"Cray"                      /* whoa! no comma! */
"on-line drawing routines",
"mouse"                   ,
"keyboard"                ,
"power cables"            , /* and what's this extra comma? */
};

我们读到:

...最后一个初始化式后面的逗号不是一个拼写错误,而是从原始c中继承下来的语法中的一个小点。它的存在或不存在是允许的,但没有任何意义。在ANSI C基本原理中声称的理由是,它使C的自动生成更容易。如果允许在每个以逗号分隔的列表中使用尾随逗号,例如在枚举声明中,或在单个声明中使用多个变量声明器,则声明将更加可信。事实并非如此。

... 对我来说,这更有意义

它允许每一行都遵循相同的形式。首先,这样可以更容易地添加新行,并让版本控制系统有效地跟踪更改,还可以更容易地分析代码。我想不出技术上的原因。

除了代码生成和编辑方便之外,如果您想实现解析器,这种类型的语法更简单、更容易实现。c#在一些地方遵循这个规则,比如在枚举定义中有一个以逗号分隔的项目列表。

因此,当两个人在不同分支的列表中添加一个新项目时,Git可以正确地合并这些更改,因为Git是按行工作的。

每个人都说添加/删除/生成行很容易,但这种语法真正的亮点是合并源文件。假设你有这样一个数组:

int ints[] = {
    3,
    9
};

假设您已经将这段代码签入存储库。

然后你的朋友编辑它,在结尾添加:

int ints[] = {
    3,
    9,
    12
};

你同时编辑它,在开头加上:

int ints[] = {
    1,
    3,
    9
};

从语义上讲,这些类型的操作(添加到开头,添加到结尾)应该是完全合并安全的,你的版本控制软件(最好是git)应该能够自动合并。遗憾的是,情况并非如此,因为你的版本在9后面没有逗号,而你朋友的版本有。然而,如果最初的版本后面有9,他们就会自动生成。

因此,我的经验法则是:如果列表跨越多行,则使用尾随逗号,如果列表在单行上,则不要使用尾随逗号。