- 论坛徽章:
- 11
|
本帖最后由 Ager 于 2012-11-06 22:15 编辑
回复 30# fergon
fergon 发表于 2012-08-31 22:36 ![]()
第4章 “空语句”
----彻底无语,为什么作者会产生这样的概念?
2.空语句
空语句在 C语言中很少用到,它的作用就是什么都不干,让计算机空转,它的主要目
的就和我们军训的时候原地踏步是一样的,是为了暂时等待其他的东西先完成。
空语句的形式为一个简单的“;”,其他什么都没有:
;
一个单独的分号就是告诉计算机,先等一等,在此暂留一步,然后再往下执行其他的
语句。
本书的作者将C语言中的空语句(Null Statement)理解为“延时作用”,我猜想,有两种可能性:
(可能性一)该作者可能是把C这样的编译型语言,用解释型语言的观念去理解了。在解释型语言中,解释器遭遇类似的语句,肯定会有一个微小的时间消耗。其实,对于C这样的编译型语言,编译器遭遇类似的语句(比如在词法分析阶段),也会有一个微小的时间消耗。但是,在编译后产生的汇编代码中,空语句用以界定程序逻辑结构的使命已无需再存续(在Syntax分析阶段它已被消化),所以,汇编代码中没有任何指令与空语句对应,所以,在最终产生的可执行代码中,根本也不存在延时效应。
(可能性二)该作者可能受其他错误教本(或网上错误信息资源)的影响,比如,在《百度知道》中(地址:http://zhidao.baidu.com/question/88102111.html),
有一个“最佳答案”就是这样的:
空语句一般有以下几个用途:
1.纯粹消耗CPU时间,起到延时的作用,但是注意一下,"雨落深山"说的有问题的,在嵌入式系统中一般不会这么用,原因如下:
・对于嵌入式系统来讲,不论是哪种系统,一般下位芯片级的时间单位为Tick,这样的处理单位对于Tick来说太粗略了。
但是在嵌入式系统中,有一种情况下会用到:
・不需要很高的精确度,并且要避免引起Task切替的延迟处理时,有时会这么用。因为起计时器进行延迟的话,超时处理会引起调度进程的轮循,出现Task切替。
2.为了程序的结构清楚,可读性好,以后扩充新功能方便。有些公司的编码规范要求,对于if/else语句等,如果分支不配对的话,需要用空语句进行配对,一般日系企业这么要求的比较多。
例如:
正常的这么做就行:
if(XXX)
{
XXXXX
}
但是编码规范要求,必须这么写
if(XXX)
{
XXXXX
}
else
{
;
}
3. 对于某些大型的软件项目,特别是一些嵌入式项目,处于自动化测试的需要,要求必须进行语句(例如,if/else语句)的配对。
在进行代码静态解析,单体测试Case抽出的时候,为了保证全路径覆盖,很多专业的高端自动测试工具,会建议进行语句(例如,if/else语句)的配对。此时对于一些不完备的分支,就会用空语句补全。
回答者: 希声和寡 | 十三级 名人
“其他回答”有两条,分别是:
雨落深山 | 八级
循环,消磨时间用的,可以用做最土的定时器。
在嵌入式系统中有广泛的用途。
空语句仅由一个分号组成,不进行任何操作。一般用于语法上要求有一条语句但实际没有任何操作的场合。例如:
for(i=1;i<10;i++); //空语句,起延时作用
仔细体察,为什么许多读者和作者,会认为C语言里的空语句是起“延时作用”的呢?
我猜想是这样的 …… 因为这样的代码,在最终的执行阶段,的确是造成了延时效应。但是,这是空语句造成的吗?
其实不是!
我们看反汇编:- 08048394 <main>:
- int main(){
- …… ……
- for(int i=1;i<10;i++);
- 804839a: c7 45 fc 01 00 00 00 movl $0x1,-0x4(%ebp)
- 80483a1: eb 04 jmp 80483a7 <main+0x13>
- 80483a3: 83 45 fc 01 addl $0x1,-0x4(%ebp)
- 80483a7: 83 7d fc 09 cmpl $0x9,-0x4(%ebp)
- 80483ab: 7e f6 jle 80483a3 <main+0xf>
- …… ……
- }
复制代码 在源程序的这一行代码中,最终消耗时间的肇因是for,具体地说,是for的控制表达式。
此处的一个分号(在这种情况下造成空语句),只是令for语句得以在此处完全结束(而不与分号后面的代码粘黏而构成一个更大的for语句)—— 我这麽说,你千万不要认为:for语句需要一个分号结尾,才能构成完整的for语句。其实,跟表达式语句(一个表达式加一个分号)不同,for语句(还有各分支/循环语句)并不需要分号作为其完整语句的结束标志。此处的分号,所构成的空语句,是充当了- for (控制表达式1; 控制表达式2; 控制表达式3) 语句X
复制代码 中的“语句X”的内容。
for在"找到"紧跟在它后面的括号(及其中的合法内容)之后,就要去“找到”紧跟在括号后面的第一个语句或第一个语句块(Statement Block)作为“语句X”,这样,一个完整的for语句就构成了。
只要能够让for语句不与其后面的代码粘黏而构成一个更大的for语句,除了起上述作用分号,其他具有界定语义独立性的逻辑功能的符号,也都可以拿来用,比如,用来界定语句块的花括号对,就可以拿来实现上述作用。
我们看反汇编:- 08048394 <main>:
- int main(){
- …… ……
- for(int i=1;i<10;i++){}
- 804839a: c7 45 fc 01 00 00 00 movl $0x1,-0x4(%ebp)
- 80483a1: eb 04 jmp 80483a7 <main+0x13>
- 80483a3: 83 45 fc 01 addl $0x1,-0x4(%ebp)
- 80483a7: 83 7d fc 09 cmpl $0x9,-0x4(%ebp)
- 80483ab: 7e f6 jle 80483a3 <main+0xf>
- …… ……
- }
复制代码 你看,与编译出来的指令,是完全一致的!
所以说,这些起着界定语义逻辑作用的符号,在生成汇编代码之前的Syntax分析阶段就已经被消化。在汇编代码以及最终的可执行代码中,这类符号是无法直观地被察觉到的。我认为,这也就是低级语言的代码序列难以“还原”成人们可以比较轻易自然解读其逻辑或结构的语言文本(比如高级编程语言程序代码)的主要原因之一。
那么,该书中把由单独一个分号所造成的空语句与“延时效应”如此直接挂钩的思路,是非常粗陋的,并且是错谬的。
(可能性三)该作者可能混淆(或没有认识到)了不同语言中的“空语句”机制。
比如,在汇编语言中,“空语句”机制由nop指令体现。nop指令,是一个有着明确的时间延宕作用的指令。
“巧合”的是,在IBM的Rexx语言中,有一种与nop指令同名的nop语句,例子如下:- if x = "ZERO" then
- nop
- else
- say "THIS NUMBER IS NOT ZERO"
复制代码 在我看到的语言手册中,只写明了,此nop语句具有跟现代高级编程语言中的由单独一个分号所构成的空语句相同的作用,至于nop语句本身是否有时间延宕作用,我就不敢贸然断言了。
其实,“空语句”是编程语言中的一个“小难点”,它带来的问题有很多,都不能轻易忽视。该书中一句“空语句在 C语言中很少用到”,恐怕实在是太浅陋了。
fergon 发表于 2012-08-31 22:36 ![]()
第3章 赋值的作用---把数据存起来
----实在是看不下去了,简直是脑残式的天马行空。
结合该书作者对“赋值”的理解的表述,我猜想,该书作者可能受一些原始又不准确的关于解释型编程语言的教本影响颇深,严重怀疑受谭老教授计算机教学体系之浸淫。
呵呵,又扯了一大通,仅供参考,望各位大虾指教,呵呵…… :)
|
|