[C陷阱和缺陷] 第1章 词法“陷阱”
有感自己的C语言在有些地方存在误区,所以重新仔细把《C陷阱和缺陷》一书翻出来看看,并写下这篇博客,用于读书总结以及日后方便自身复习。
第1章 词法“陷阱”
1.1 =不同与==
=是赋值操作符,而==是作为比较操作符,初学者容易将==错写为=,这种情况下编译器不会报错,这就有可能造成很严重的后果,还不容易发现。比如下面这个例子:
while( c=' ' || c=='\t' || c=='\n' ) { ; }
即使 c 既不等于'\t',也不等于'\n',但由于' '赋给 c,' '不为 0,所以 while 始终为真,成为死循环。所以有时采取下面这张写法,就能尽可能地避免这种错误(个人不太喜欢),即使错写为=,编译器也会报错进行提醒:
while( ' '=c || '\t'==c || '\n'==c ) { ; }
1.2 词法分析中的“贪心法”
当编译器读入一个字符'/'后又跟了一个字符'*',那么编译器就必须做出判断:是将其作为两个独立的符号对待,还是合并起来作为一个符号对待。C语言对这个问题的解决方案可以归纳为一个很简单的规则:每一个符号应该包含尽可能多的字符。
也就是说,编译器将程序分解成符号的方法是,从左到右一个字符一个字符地读入,如果该字符可能组成一个符号,那么再读入下一个字符,判断两个读入字符合并成的字符串是否可能是一个字符的组成部分;如果可能,继续读入下一个字符,重复上述判断,直到读入的字符组成的字符串已不再可能组成一个有意义的符号。这个策略有时被称为“贪心法”。
需要注意的是,除了字符串和字符常量,符号的中间不能嵌有空白(空白、制表符、换行符)。例如,==是单个符号,= =是两个符号,表达式a---b与 表达式a -- - b的含义相同,与表达式a - --b的含义不同。看下面这个例子:
y = x/*p; // x除以p指向的内容
而实际上,/*被编译器理解为一段注释的开始,也就是说,该语句会将x之间赋给y,后面全是注释。必须这么写才对:
y = x / *p; // 正确
或者更加清楚一点,使用括号:
y = x/(*p); //正确
1.3 整型常量
如果一个整型变量的第一个字符是数字0,那么该常量将被视为八进制数。因此,10与010的含义完全不同。例如,0195的含义是1*8^2 + 9*8^1 + 5*8^0,也就是141(十进制)或者0215(八进制)。
需要注意这种情况,有时候在上下文中为了格式对齐的需要,可能无意间将十进制数写成了八进制数,例如:
struct
{
int part_number;
char *description;
} porttab[ ] = {
046, "left-handed widget" ,
047, "right-handed widget" ,
125, "frammis"
}
1.4 字符与字符串
C语言中的单引号和双引号含义完全不同,用单引号引起的一个字符实际上表示一个整数,例如'a'的含义与97(十进制)严格一致。而即使是用双引号引起的一个字符,也是指向一个无名数组首个字符的指针,该数组被双引号之间的字符以及字符'\0'初始化。
下面的这个语句:
printf("Hello world\n");
与
char hello[ ] = { 'H', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '\n' };
是等效的。
因为用单引号引起的一个字符代表一个整数,而用双引号引起的一个字符代表一个指针,所以两者不能混用,否则编译器的类型检查功能将会检查到错误:
char *p = 'a'; // error!
[C陷阱和缺陷] 第1章 词法“陷阱”的更多相关文章
- [C陷阱和缺陷] 第3章 语义“陷阱”
第3章 语义"陷阱" 一个句子哪怕其中的每个单词都拼写正确,而且语法也无懈可击,仍然可能有歧义或者并非书写者希望表达的意思.程序也有可能表面上是一个意思,而实际上的意思却相 ...
- [C陷阱和缺陷] 第2章 语法“陷阱”
第2章 语法陷阱 2.1 理解函数声明 当计算机启动时,硬件将调用首地址为0位置的子例程,为了模拟开机时的情形,必须设计出一个C语言,以显示调用该子例程,经过一段时间的思考,得出语句如下: ( * ...
- 《C陷阱与缺陷》之1词法"陷阱"
编译器中负责将程序分解为一个一个符号的部分,一般称为"词法分析器".在C语言中,符号之间的空白(包括空格符.制表符或换行符)将被忽略. 1.=不同于== C语言使用符号" ...
- 《C陷阱与缺陷》之1词法"陷阱"
编译器中负责将程序分解为一个一个符号的部分,一般称为"词法分析器".在C语言中,符号之间的空白(包括空格符.制表符或换行符)将被忽略. 1.=不同于== C语言使用符号" ...
- C陷阱与缺陷代码分析之第1章词法陷阱
作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz 编译器中负责将程序分解为一个一个符号的部分,称为“词法分析器”.下面看一个例子: if(x > big) bi ...
- c缺陷与陷阱笔记-第一章 词法陷阱
1.运算符的贪心性,匹配最长的运算符,例如 n-->0,从-开始,-是运算符,--是运算符,-->就不是,所以是 n -- > 0,--是 a---b,-是,--是,,---不是,所 ...
- 《C陷阱与缺陷》 第0章导读 第1章词法陷阱
1.= 与==的区别 赋值运算符= 的优先级要小于逻辑运算符== 也就是说,会进行先逻辑上的比较,然后再把比较结果进行赋值,很合理. getc库是什么??? 1.C语言中有单字符 = 也有多字符单元如 ...
- [C陷阱和缺陷] 第7章 可移植性缺陷
C语言在许多不同的系统平台上都有实现.的确,使用C语言编写程序的一个首要原因就是,C程序能够方便地在不同的编程环境中移植. 不同的系统有不同的需求,因此我们应该能够预料到,机器不同则其上的C语 ...
- [C陷阱和缺陷] 第6章 预处理器
在严格意义上的编译过程开始之前,C语言预处理器首先对程序代码作了必要的转换处理.因此,我们运行的程序实际上并不是我们所写的程序.预处理器使得编程者可以简化某些工作,它的重要性可以由两个主要的原因说 ...
随机推荐
- bzoj 2223 [Coci 2009]PATULJCI
[Coci 2009]PATULJCI Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 1286 Solved: 553[Submit][Status ...
- poj1655(dfs,树形dp,树的重心)(点分治基础)
题意:就是裸的求树的重心. #include<cstring> #include<algorithm> #include<cmath> #include<cs ...
- 贝尔数--Codeforces908E. New Year and Entity Enumeration
给n<=50个长度m<=1000的二进制数,记他们为集合T,求满足下面条件的集合S数:令$M=2^m-1$,1.$a \epsilon S \Rightarrow a \ \ xor \ ...
- 如何爬取可用的IP代理
上一篇说到对付反爬虫有一个很关键的方法就是使用IP代理,那么我们应该如何获取这些可用的IP代理呢?这里分享一下自己这两天的一些爬取IP代理的心得体会. 1 步骤 1.找到几个提供免费IP代理的网站,获 ...
- School Marks-CodeForces
B. School Marks time limit per test 2 seconds memory limit per test 256 megabytes input standard inp ...
- Linux下tomcat的catalina.out屏蔽
修改catalina.sh ,找到下面的位置: if [ -z "$CATALINA_OUT" ] ; then#CATALINA_OUT="$CATALINA_BASE ...
- 使用Tornado实现http代理
0x00 http代理 http代理的用处非常多,市面上也有公开的代理,可是有时候为了工作须要,比方分析应用层流量.做数据訪问控制.甚至做监控等等.Tornado提供了一些非常方便的环境和API,我们 ...
- Codeforces Round #247 (Div. 2) B
B. Shower Line time limit per test 1 second memory limit per test 256 megabytes input standard input ...
- 滚动载入server端内容——样例
网页代码例如以下 <!doctype html> <html> <head> <meta charset="utf-8"> < ...
- socket简单理解
要想理解socket首先得熟悉一下TCP/IP协议族, TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制协议/网间协议,定义了主 ...