读《C陷进与缺陷》笔记

无意中觅得的好书,这本书总结了很多程序员的错误经验。


词法“陷阱”

编译器中负责将程序分解为一个一个符号的部分,叫“词法分析器”。


1.显示比较。

当需要对变量赋值后,并检查改变量的新值是否为0时,为了避免编译器的警告,我们应该显示的进行比较。

例如:

if(x = y)
    fun();
应该写作:
if((x = y) != 0)
    fun();
很明显下面的代码意图一目了然。



2.词法分析中的“贪心法”

C语言中的符号,例如/*=,只有一个字符长,称为单字符符号。而例如/*==,称为多字符符号。

当C编译器读入字符/后又跟了一个字符*,那应该做出判断:是当做两个单独字符,还是合起来当做一个字符对待。

C编译器的解决方法就是“贪心法”,一个一个读入字符,如果能合起来组成一个字符,又继续读,直到读入的字符不可能和之前的字符们组成一个有意义的字符。

需要注意的是,(除了字符串、字符常量)符号的中间不能有空白(空格符、制表符、换行符)。
例如见下面表达式:

a---b   等价于 a -- - b    等价于 (a--)-b
而(上面下面不等价)
a - -- b    等价于 a-(--b)

再例如:
想要表达用x除以p指向的值,再把商赋值给y。

y = x/*p        /* p指向除数*/
这个就是错的,编译器会理解成把x赋值给y,它把/*理解为一段注释的开始,并不断读入字符,直到*/出现为止。

y = x / *p      /* p指向除数 */
y = x/(*p)      /* p指向除数 */
这两种才能正确表达意思。



3.字符与字符串

单引号引起的一个字符代表一个整数,整数值为该字符在编码器中采用的字符集中的序列值。对于采用ASCII字符集的编译器而言,'a'的含义与97(十进制)或者0141(八进制)完全一致。

双引号引起的字符串,代表的是一个指向无名数组起始字符的指针。该数组被 双引号之间的字符 和 一个额外的二进制为零的字符'\0' 初始化。
这里写图片描述

printf("Hello \n");
等价于
char h[] = {'H','e','l','l','o',' ','\n','\0'};
printf(h);
等价于
char h[] = {'H','e','l','l','o',' ','\n',0};
printf(h);

这里写图片描述



因为单引号括起的一个字符代表一个整数,而双引号括起的一个字符代表一个指针,所以不能混用。例如:

char *s = '/';

编译器会报错,因为'/'只是一个整数,而不是一个指针。



整型数的存储空间存储空间可以容纳多个字符(一般4个,每个占2位),所以C编译器允许在一个字符常量中包括多个字符。例如:'yes',在VC++6.0中,编译器一个一个读入字符时,将会依次用后一个字符覆盖前一个字符,最后就得到最后一个字符的整数值。例如下图:
这里写图片描述

这里写图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值