《码出高效》学习笔记与书中错误记录
今天在阅读《码出高效》的时候看到了一个问题,我也是第一次知道,而且有点颠覆我的认知。所以做了一些测试,并记录下来。
然而测试的结果发现,好像事实并不如书中说的那么简单。
问题是这样的:
if (true) int x; for (; ; ) int y; while (true) int z;
这三句话,能通过编译吗,如果能,会给出 Warning 吗,如果不能,那么错误信息是什么。
书中给出的答案是,不能通过编译,会给出 Declaration not allowed here 编译错误信息,并对此,书中解释为:
单语句在没有加大括号的情况下,声明的变量不可能再被使用,编译器认为没有任何意义。
Every declaration that introduces a name has a scope, in which they can be used.
我做了一些测试,发现事情好像并不是那么简单。
我一开始也是这样认为的。我本来以为,至少应该通过编译,最多是给一个 Warning 说 variable is never used
。
我比较好奇,除了 Java,其他语言会不会有同样的编译错误。
首先是是测试 C、C++、Java 是不是都对这句话有相同的结果。
先来看 C,测试环境是 CentOS 7.3 x64,GCC 版本是 gcc version 4.8.5 20150623 (Red Hat 4.8.5-28) (GCC)。
C,不管是 ANSI C 还是 C99,都无法通过编译,直接给出 Error。
error: expected expression before ‘int’
如果加上大括号,那么能够通过编译,遇到大家常见的 Warning。
warning: unused variable ‘x’ [-Wunused-variable]
同样的结果在环境中(我测试环境是 CodeBlocks,Windows)得到了相同的结果。
我相信,CLion 等 IDE 也有一样的结果,如果没有,那么可能是 IDE 帮忙优化了,毕竟有些时候,写 C 代码漏 include 一些头文件,编译和运行的结果也是正确的(IDE 帮你自动补上了)。
原因稍后分析,下面继续测试。
C++。
结果是,编译通过,给出 Warning。
事实上与代码无关,即使是对刚才的 .c
文件,只要使用 g++ 编译器,也是通过的。
再来看 Java。
public class Main { public static void main(String args[]) { if (true) int jxtxzzw; } }
如果是 Eclipse,直接给出错误。
强行运行,编译失败,无法运行。
Unresolved compilation problem: Syntax error on token “)”, Statement expected after this token at …
如果是 IDEA,会给出编译错误信息。
Declaration not allowed here
至于为什么 C 就不行呢?难道 C 的语法什么地方说了这是不合法的吗?闻所未闻啊?
但是既然 C 的编译器说不行,那肯定是 C 的哪个标准说了这是不合法的,如果这是真的,那么就不是作用域的问题,而是语法、文法的问题。
换句话说,如果 if (true) {int x;}
是合法的,那为什么 if (true) int x;
就不符合语法呢?
我查阅了很多资料(链接见文末),最后找到一个比较信服的答案——确实,根据 C 标准,这就是错的,彻底的语法错误。
首先来澄清一个概念,if
条件句后面,必须跟一个语句。
int x
是一个声明,Declaration。
int x = 10;
是一个定义,Definition。
{int x;}
或者 {int x = 10;}
由于有了 {}
,是一条语句,Statement。
这是 3 个完全不同的概念,也是绝大多数程序员从一开始就分不清的,而且也始终分不清,从来分不清。
所以,现在的问题的答案就很显然了,C 要求 if 后面是一条语句,然而文章一开始那种写法,是 Declaration,不是 Statement,所以语法就是错的。
这也印证了那句 Error:expected expression
,我需要一个表达式。
表达式 Expression,显然是一句语句 Statement。
同时,这与 Eclipse 的报错信息是一致的——if 后面需要一个 Statement。( Statement expected after this token at … )
如果从这个角度考虑,那么,IDEA 的错误提示,Declaration not allowed 就不应该从变量作用域的角度考虑这里的变量声明不合法,而是应该理解成,这是一个 Declaration,而我需要一个 Statement,所以 Declaration 在这里是不被允许的。
这是一个 Declaration,而我需要一个 Statement,所以 Declaration 在这里是不被允许的
至于为什么 g++ 就可以,我想这个问题,可能和 为什么有些 IDE 这么写就可以通过编译,我猜想的是(是的,只是猜想,没有验证过),恐怕是这个编译器,包括绝大多数的 IDE,都自动优化了这个地方,把所有的 if 等语句后面,默认当作套上了大括号在处理,即使是单语句,也假装有了一个大括号作用域,然后再编译的。
所以,有些 gcc 的编译器,也有可能可以,但是从我的测试情况来看,MinGW、Cygwin、Windows、Window 的 Ubuntu 子系统、CentOS 下,gcc 都会给出 error。
I guess the counter-intuitive part of the question is: if this is correct C:
if (a == 1) { int b = 10;}
then why is this not also correct C?
if (a == 1) int b = 10;
I mean, a one-line conditional if statement should be fine either with or without braces, right?
The answer lies in the grammar of the if statement, as defined by the C standard. The relevant parts of the grammar I’ve quoted below. > Succinctly: the int b = 10 line is a declaration, not a statement, and the grammar for the if statement requires a statement after the conditional that it’s testing. But if you enclose the declaration in braces, it becomes a statement and everything’s well.
见: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf 以及 https://www.quora.com/What-does-error-expected-expression-before-int-mean-in-C

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
2019年最全最系统的大数据学习路线
一,题记 要说当下IT行业什么最火?ABC无出其右。所谓ABC者,AI + Big Data + Cloud也,即人工智能、大数据和云计算(云平台)。每个领域目前都有行业领袖在引领前行,今天我们来讨论下大数据Big Data这个方向。 二,大数据里面的角色 角色一:大数据工程 大数据工程需要解决数据的定义、收集、计算与保存的工作,因此大数据工程师们在设计和部署这样的系统时首要考虑的是数据高可用的问题,即大数据工程系统需要实时地为下游业务系统或分析系统提供数据服务; 角色二:大数据分析 大数据分析角色定位于如何利用数据——即从大数据工程系统中接收到数据之后如何为企业或组织提供有产出的数据分析,并且确实能够帮助到公司进行业务改善或提升服务水平,所以对于大数据分析师来说,他们首要解决的问题是发现并利用数据的价值,具体可能包括:趋势分析、模型建立以及预测分析等。 这两类角色相互依存但又独立运作,何意?没有大数据工程,大数据分析便无从谈起;但倘若没有大数据分析,我也实在想不出大数据工程存在的理由。这就类似于结婚和谈恋爱——恋爱的目的是为了结婚,且不以结婚为目的的谈恋爱都是耍流氓。 简单总结一下,...
- 下一篇
C++之父:精通C++很难,但你一天之内就能学习使用C++
精通C++听起来好像就是一个笑话。为什么C++比别的语言难学那么多?其实这基本上是因为C++之父Bjarne Stroustrup 说过的一句话“我特别的讨厌语言的设计者把自己的喜好强加给用户”(看向go)。结果C++为了不限制你的想法,于是也就变成了现在的样子-- ,那么如何学好C++,甚至是出色掌握C++? 1.谈谈C++的书籍。 没有,也不可能有一本书对于所有人来说都是最好的。不过对于那些真正的程序员来说,如果他喜欢从“经典风格”的书中间学习一些新的概念和技术,我推荐我的The C++ Programming Language, 1998年的第三版和特别版。那本书讲的是纯而又纯的C++,完全独立于平台和库(当然得讲到标准库)。该书面向那些有一定经验的程序员,帮助他们掌握C++,但不适合毫无经验的初学者入门,也不适合那些临时程序员品尝C++快餐。所以这本书的重点在于概念和技术,而且在完整性和精确性上下了不少功夫。 学习C++要花多长时间? 这要看你说的“学习”是什么意思了。如果你是一个Pascal程序员,你应该能很快地使你的C++水平达到与Pascal相近的程度;而如果你是一个C程...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- CentOS7安装Docker,走上虚拟化容器引擎之路
- SpringBoot2全家桶,快速入门学习开发网站教程
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS8编译安装MySQL8.0.19
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- CentOS7,CentOS8安装Elasticsearch6.8.6
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- SpringBoot2整合Thymeleaf,官方推荐html解决方案