C++ int a[]={1,2,};允许使用奇怪的逗号。有什么特别的原因吗?
也许我不是这个星球的人,但在我看来,以下应该是一个语法错误:C++ int a[]={1,2,};允许使用奇怪的逗号。有什么特别的原因吗?,c++,syntax,grammar,language-lawyer,C++,Syntax,Grammar,Language Lawyer,也许我不是这个星球的人,但在我看来,以下应该是一个语法错误: int a[] = {1,2,}; //extra comma in the end 但事实并非如此。在VisualStudio编译此代码时,我感到惊讶,但我已经学会不相信C++的规则,所以我检查了标准,并且它也允许标准的 < /强>。如果你不相信我,你可以看8.5.1的语法规则 为什么允许这样做?这可能是一个愚蠢而无用的问题,但我想让你明白我为什么要问这个问题。如果这是一般语法规则的一个子案例,我会理解——他们决定不让一般语法变
int a[] = {1,2,}; //extra comma in the end
但事实并非如此。在VisualStudio编译此代码时,我感到惊讶,但我已经学会不相信C++的规则,所以我检查了标准,并且它也允许标准的<强> < /强>。如果你不相信我,你可以看8.5.1的语法规则
为什么允许这样做?这可能是一个愚蠢而无用的问题,但我想让你明白我为什么要问这个问题。如果这是一般语法规则的一个子案例,我会理解——他们决定不让一般语法变得更难,只是不允许在初始值设定项列表的末尾使用多余的逗号。但是不允许,额外的逗号是明确允许的。例如,函数调用参数列表的末尾不允许有多余的逗号(当函数采用…
)时),这是正常的
那么,还有什么特别的原因可以明确地允许使用这个多余的逗号吗?我一直认为它可以更容易地附加额外的元素:
int a[] = {
5,
6,
};
就变成了:
int a[] = {
5,
6,
7,
};
在以后的日期。它使生成源代码变得更容易,也使编写可以在以后轻松扩展的代码变得更容易。考虑添加额外条目到:所需的内容
int a[] = {
1,
2,
3
};
。。。必须在现有行中添加逗号,然后添加新行。将其与三个后面已经有一个逗号的情况进行比较,您只需添加一行即可。同样,如果您想删除一行,您可以这样做,而不必担心它是否是最后一行,并且您可以重新排序行,而不必使用逗号。基本上,这意味着你对待线条的方式是一致的
现在考虑生成代码。类似于(伪代码):
输出(“inta[]={”);
对于(int i=0;i
无需担心您正在填写的当前项目是第一项还是最后一项。更简单。如果您这样做会很有用:
int a[] = {
1,
2,
3, //You can delete this line and it's still valid
};
原因很简单:添加/删除行很容易 想象一下下面的代码:
int a[] = {
1,
2,
//3, // - not needed any more
};
现在,您可以轻松地向列表中添加/删除项,而不必有时添加/删除尾部逗号
与其他答案不同的是,我并不认为生成列表的简单性是一个合理的理由:毕竟,代码在最后一行(或第一行)进行特殊处理是微不足道的。代码生成器编写一次,使用多次。它允许每一行遵循相同的形式。首先,这样可以更容易地添加新行,让版本控制系统有意义地跟踪更改,还可以更轻松地分析代码。我想不出技术上的原因。我认为开发人员使用起来很方便
int a[] = {
1,
2,
2,
2,
2,
2, /*line I could comment out easily without having to remove the previous comma*/
}
此外,如果出于任何原因,您有一个为您生成代码的工具;工具不必关心它是否是初始化中的最后一项。据我所知,允许这样做的原因之一是自动生成代码应该很简单;您不需要对最后一个元素进行任何特殊处理。它使生成数组或枚举的代码生成器更容易 想象一下:
std::cout << "enum Items {\n";
for(Items::iterator i(items.begin()), j(items.end); i != j; ++i)
std::cout << *i << ",\n";
std::cout << "};\n";
出于向后兼容性的原因,我认为允许使用尾随逗号。有很多现有的代码,主要是自动生成的,它在后面加了一个逗号。它使编写循环变得更容易,在最后没有特殊条件。 e、 g
对于每个(my_inits.begin()、my_inits.end(),
[](常量标准::字符串和值){std::cout在实践中,唯一不允许使用的语言是Javascript,它会导致无数的问题。例如,如果您从数组中间复制并粘贴一行,将其粘贴到最后,并且忘记删除逗号,那么您的站点将完全被IE访问者破坏
*理论上这是允许的,但Internet Explorer没有遵循标准,并将其视为一个错误这对于机器来说更容易,即解析和生成代码。
这对人类来说也更容易,即通过一致性进行修改、注释和视觉优雅
假设C,你会写下面的内容吗
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
puts("Line 1");
puts("Line 2");
puts("Line 3");
return EXIT_SUCCESS
}
#包括
#包括
内部主(空)
{
看跌期权(“第1行”);
看跌期权(“第2行”);
看跌期权(“第3行”);
返回退出成功
}
不。不仅因为final语句是一个错误,还因为它是不一致的。那么为什么对集合也要这样做呢?即使是在允许您省略最后分号和逗号的语言中,社区通常也不喜欢它。例如,Perl社区似乎不喜欢省略分号,除了一行程序。他们将其应用于com妈妈也是
不要在多行集合中省略逗号,因为你不会在多行代码块中使用分号。我的意思是,即使语言允许,你也不会这样做,对吗?所有人都说添加/删除/生成行的方便性是正确的,但这种语法真正的亮点是在合并时将源文件放在一起。假设您拥有以下阵列:
int ints[] = {
3,
9
};
假设您已将此代码签入存储库
然后,您的好友对其进行编辑,并在末尾添加:
int ints[] = {
3,
9,
12
};
同时对其进行编辑,并在开头添加:
int ints[] = {
1,
3,
9
};
从语义上讲,这些类型的操作(添加到开头,添加到结尾)应该是完全合并安全的,并且您的版本控制软件(希望是git)应该能够自动合并。遗憾的是,情况并非如此,因为您的版本在9后面没有逗号,而您的好友的版本在9后面没有逗号。然而,如果原始版本后面有9,它们将自动合并
因此,我的经验法则是:如果列表跨越多行,请使用尾随逗号;如果列表位于一行,请不要使用逗号。此外
int ints[] = {
3,
9
};
int ints[] = {
3,
9,
12
};
int ints[] = {
1,
3,
9
};
#include <iostream>
#include <string>
#include <cstddef>
#define ARRAY_SIZE(array) (sizeof(array) / sizeof *(array))
int main() {
std::string messages[] = {
"Stack Overflow",
"Super User",
"Server Fault"
};
size_t i;
for (i = 0; i < ARRAY_SIZE(messages); i++) {
std::cout << messages[i] << std::endl;
}
}
Stack Overflow
Super User
Server Fault
#include <iostream>
#include <string>
#include <cstddef>
#define ARRAY_SIZE(array) (sizeof(array) / sizeof *(array))
int main() {
std::string messages[] = {
"Stack Overflow",
"Server Fault"
"Super User",
};
size_t i;
for (i = 0; i < ARRAY_SIZE(messages); i++) {
std::cout << messages[i] << std::endl;
}
}
Stack Overflow
Server FaultSuper User
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? */
};
int a [] = {
#ifdef A
1, //this can be last if B and C is undefined
#endif
#ifdef B
2,
#endif
#ifdef C
3,
#endif
};
#define LIST_BEGIN int a[] = {
#define LIST_ENTRY(x) x,
#define LIST_END };
LIST_BEGIN
LIST_ENTRY(1)
LIST_ENTRY(2)
LIST_END
#define LIST_LAST_ENTRY(x) x