赋值语句@赋值表达式@便于阅读和便于理解的比较
文章目录
- 赋值表达式
- 便于阅读和便于理解的比较
赋值表达式
对于经验比较丰富的C 语言程序员,可以把这个字符复制程序编写得更精炼一些。在C 语言中,类似于 c = getchar()
之类的赋值操作是一个表达式,并且具有一个值,即赋值后左边变量保存的值。
也就是说, 赋值可以作为更大的表达式的一部分出现。
#include <stdio.h>/* copy input to output; 2nd version */
main()
{int a = 1, b = 3, c, d, e, f;d = (c = a + b) - 2; // 这个语句相当于c=a+b;d=c-2;也就是将c,d的赋值操作在一个语句内完成f = e = b - a; //将e,f都赋值为b-a;相当于e=b-a;f=e;printf("c=%d;d=%d;\n", c, d);printf("e=%d;f=%d;\n", e, f);
}
如果将为c赋值的操作放在while循环语句的测 试部分中,上述字符复制程序便可以改写成下列形式:
#include <stdio.h>/* copy input to output; 2nd version */
main()
{int c;while ((c = getchar()) != EOF)putchar(c);
}
在该程序中,while
循环语句首先读一个字符并将其赋值给c
,然后测试该字符是否为文件 结束标志。如果该字符不是文件结束标志,则执行while语句体,并打印该字符。随后重复 执行while
语句。当到达输入的结尾位置时,while
循环语句终止执行,从而整个main
函 数执行结束。
以上这段程序将输入集中化,getchar
函数在程序中只出现了一次,这样就缩短了程序, 整个程序看起来更紧凑。习惯这种风格后,读者就会发现按照这种方式编写的程序更易阅读。 我们经常会看到这种风格。(不过,如果我们过多地使用这种类型的复杂语句,编写的程序可能会很难理解,应尽量避免这种情况。)
更容易阅读,或者方便阅读不表示容易理解,比如简短的语句看似简单,但是可能应用了更多的技巧,比朴素啰嗦的语句更难理解
对while语句的条件部分来说,赋值表达式两边的圆括号不能省略。不等于运算符!=的 优先级比赋值运算符=
的优先级要高,这样,在不使用圆括号的情况下关系测试!=
将在赋值=
操作之前执行。
因此语句 c = getchar() != EOF
等价于语句 c = (getchar() != EOF)
该语句执行后,c的值将被置为0 或1
便于阅读和便于理解的比较
下面三个版本的代码功能等价,但是阅读的方便性和理解的难易程度各不相同;在下面的例子中,两个属性类似于此消彼长
第一种最直观,最容易理解,但是代码量最多;第二种到第三种语句越发简洁,但是需要掌握的技巧越多
不过随着经验的增加,或者对于有经验的人来说,最后一种不仅代码格式上工整对称,功能明确,是优先选择的写法
下面是一个strcpy
字符串复制功能的简易版本(准库(<string.h>)中提供的函数strcpy把目标字符串作为函数值返回)
/* strcpy: copy t to s; pointer version */
void strcpy(char *s, char *t)
{int i;i = 0;while ((*s = *t) != '\0'){s++;t++;}
}
在下面的版本中,s 和t 的自增运算放到了循环的测试部分中。表达式*t++的值是执行自增运算之前t所指向的字符。后缀运算符++表示在读取该字符之后才改变t的值。同样的道理,在s 执行自增运算之前,字符就被存储到了指针s 指向的旧位置。
该字符值同时也用来和空 字符’\0’进行比较运算,以控制循环的执行。最后的结果是依次将t指向的字符复制到s指向的位置,直到遇到结束符’\0’为止(同时也复制该结束符),
/* strcpy: copy t to s; pointer version 2 */
void strcpy(char *s, char *t)
{while ((*s++ = *t++) != '\0');
}
为了更进一步地精炼程序,我们注意到,表达式同’\0’的比较是多余的,因为只需要判断表达式的值是否为0 即可。因此,该函数可进一步写成下列形式:
/* strcpy: copy t to s; pointer version 2 */
void strcpy(char *s, char *t)
{while ((*s++ = *t++));
}
该函数初看起来不太容易理解,但这种表示方法是很有好处的,我们应该掌握这种方法,C 语言程序中经常会采用这种写法。