Tom*_*son 93 c c++ cross-language language-lawyer
if (1) int a = 2;
Run Code Online (Sandbox Code Playgroud)
这行代码是有效的 C++ 代码(至少可以编译)但无效的 C 代码(无法编译)。我知道语言之间存在差异,但这一差异是出乎意料的。
我一直以为语法是
if (expr) statement
Run Code Online (Sandbox Code Playgroud)
但这将使其在两者中都有效。
我的问题是:
Chr*_*odd 90
这是 C 和 C++ 之间微妙而重要的区别。在 C++ 中,任何语句都可以是声明语句。在 C 语言中,没有声明语句这样的东西;相反,在任何复合语句中都可以出现声明而不是语句。
来自 C 语法(C17 规范):
复合语句:“{”块项目列表选择“}”
块项目列表:块项目| 块项目列表 块项目
块项目:声明| 陈述
来自 C++ 语法(C++14 规范):
复合语句:“{”语句序列选择“}”
语句序列: 语句| 语句-seq 语句
语句: ... | 声明-声明| ...
目前尚不清楚为什么存在这种差异,这只是语言进化的方式。C++ 语法可以追溯到(至少)C++85。C 语法是在 C89 和 C99 之间的某个时候引入的(在 C89 中,声明必须位于块的开头)
在 C++ 的原始 85 和 89 版本中,声明语句中定义的变量的范围是“直到封闭块的末尾”。因此,这样的声明if
不会立即超出范围(就像在较新的版本中那样),而是位于同一块作用域中 if 后面的语句的范围内。当条件为假时,这可能会导致访问未初始化数据时出现问题。更糟糕的是,如果 var 有一个重要的析构函数,那么当作用域结束时就会调用它,即使它从未被初始化!我怀疑试图避免此类问题导致 C 采用不同的语法。
bol*_*lov 75
克里斯的回答(和其他人)显示了语法的不同之处。
我想指出这if (1) int a = 2;
在 C 中没有意义,但在 C++ 中却有意义。由于我们没有块,只有 1 个语句/声明,因此无法进一步使用声明的变量(它立即超出范围)。在 C 中,允许这样做是没有意义的,但在 C++ 中,构造函数和析构函数可能会产生副作用,因此定义和初始化立即超出范围的变量可能很有用,并且必须允许。
Kei*_*son 28
这是因为C和C++定义语句不同。
在 C 语言中,声明不属于语句。C 复合语句由开头、块项{
的选项列表和结尾组成,其中块项可以是声明或语句。(这一点在 C99 中发生了变化,C 添加了在块内混合声明和语句的功能。)}
在 C++ 中,声明被归类为语句(但前提是它位于复合语句内)。这允许更简单地定义复合语句:它是 a {
,后跟可选的语句列表,最后是 a }
。
这种差异并没有太大的实际作用;总是可以解决它的。一个影响是,在 C++ 中紧跟在 case 标签后面的声明是合法的,但在 C 中这是不合法的。