C:表达式、语句、声明

  有网友在129楼问

  “表达式、语句、声明之间的区别到底是什么?”

  这个问题对很多人来说确实很模糊,甚至很多出版物中也有很多错误的讲述,故此本文力图对此做一详尽说明和澄清。

表达式(Expression)

根据C标准,表达式(Expression)是运算符(operator)和操作数(operand)所构成的序列,例如”3+2″。最简单的情形,也可能没有运算符,例如“3”。

可能需要特意提一下的是,函数调用也是表达式。例如 sqrt(1.0),这里的“()”是一个运算符,sqrt和1.0则是“()”这个运算符的操作数。

表达式所表达的可能是要求计算机进行值的计算(computation of a value),例如“3+2”这个表达式,美国空间,表示的就是要求计算机求3+2的值。当然,表达式同时也表示这个计算所得到的值。

表达式还可能用来指明一个数据对象(object)或一个函数(function)。例如,若有 int i; 那么在 i = 1 这个表达式中的 i 这个子表达式就是指 i 所代表的那个object——一块连续的内存。再比如, 表达式 & printf 中,printf这个子表达式表示的是相应的printf()库函数。

除此之外,表达式可能产生副效应(side effects),例如printf(“ABC”) 这个表达式的值是3,其副效应是在标准输出设备上连续输出A、B、C这三个字符。再比如,对于int i; 表达式 i = 3 的值是3,副效应是 i 所代表的数据对象被写入了3。

语句(Statement)

C语言语句(Statement)的定义从其功能上来说有些含糊:语句规定的是一种“动作”(action)。这种动作最显著的特点是规定了如何跳转或结束。例如,对于int i; “i = 1 ;”这条语句的意义是到“;”位置时 i = 1 这个表达式求值(Evaluate),即值的计算和副效应必须完成。再比如“return ;”语句规定的是跳转到另一位置继续执行。

尽管语句的功能有些含糊,但其语法形式确实极其清晰的。形式上较为简单的语句有:

表达式语句(expression-statement),形式为:

expression ;

其中的表达式是可选的。这种语句以“;”作为结束标志。对于初学者来说最常见的表达式语句是调用printf()函数所形成的:printf(“Hello World\n”);

跳转语句(jump-statement),包括:

goto语句、continue语句、break语句和return语句。这种语句也以“;”作为结束标志。

复合语句(compound-statement),其一般形式为:

{block-item-list}

其中的block-item-list可以有也可以没有,可以是声明,也可以是语句。

有一点特别需要说明,复合语句并非以“;”作为结束标志。这表明语句中不一定有“;”。国内C语言书中有一种常见的陈词滥调:“一个语句必须在最后有一个分号,分号是语句中不可缺少的组成部分”(谭浩强,《C程序设计》第四版,p58),那绝对在是瞪着眼睛说胡话。因为复合语句的最后就不需要有分号。最简单的复合语句只有一对“{}”,根本就没分号什么事儿。

其他的语句都是构造性的,即是在其他语句的基础上构造出来的。比如标号语句(labeled-statement),就是在语句前加一冒号及其他内容:

identifier : statement

case constant-expression : statement

default : statement

选择语句也是依据类似的原则在语句的基础上构造的:

if ( expression ) statement if ( expression ) statement else statement switch ( expression ) statement

值得一提的是switch语句并不一定是在复合语句的基础上构造的,这和很多人的常识不同。例如,

switch ( i ) case 0:case 1:case 2:printf(“ABC\n”);

就是一条完全合法的switch语句。其功能等价于

if (i==0||i==1||i==2)printf(“ABC\n”);

C语言的循环语句同样是在语句的基础上构造而成。

while ( expression ) statement  do statement while ( expression ) ; for ( expressionopt ; expression ; expression ) statementfor ( declaration expression; expression ) statement

在这些语句中,只有do-while语句最后一定是以“;”作为结束标志。

总之,由于复合语句并不是以分号作为结束标志,而很多语句都是在语句的基础上进一步构造而成,因此除了表达式语句、跳转语句及do-while语句一定是以分号结束,其他语句则可能以分号结束,也可能不以分号结束,分号并不是语句必须的组成部分。

声明(Declarations)

  除了static_assert declaration(C11),声明的作用都是向编译器解释一个或多个标识符的含义及属性。

C标准给出的声明的一般形式为

declaration-specifiers init-declarator-list ;

因此,通常情况下声明都有“;”。

但实际上,函数定义同时也是声明(A definition of an identifier is a declaration),在格式上却与此不符。

尽管功能明确,形式简单,但声明其实是C语言中最复杂的成分,至少是之一。这种复杂性被declarator 漠然地掩盖起来了。

C语言要求每个声明至少要声明一个declarator 、一个tag或一个枚举成员。也就是说

int i ;//没问题,i是declarator

int ; //违法,无declarator

struct t;//合法,声明了一个tag——t

enum { A };//是合法的,声明了枚举成员A

struct { int a ;}; //违背语言要求,可能招致警告。(在C语言早期,并不违反标准)

union { int a ;}; //违背语言要求,可能招致警告。(在C语言早期,并不违反标准)

总结失败的原因能够让人越来越谨慎。

C:表达式、语句、声明

相关文章:

你感兴趣的文章:

标签云: