作者:刘昊昱

博客:http://blog.csdn.net/liuhaoyutz

编译器中负责将程序分解为一个一个符号的部分,称为“词法分析器”。下面看一个例子:

if(x > big) big = x;

这个语句的第一个符号是C语言的关键字if,紧接着下一个符号是左括号,再下一个符号是标识符x,再下一个是大于号,再下一个是标识符big,依次类推。在C语言中,符号之间的空白符将被忽略。

本章将探讨符号和组成符号的字符间的关系,以及有关符号含义的一些常见误解。

陷阱1 “=”不同于“==”

将相等符号”==”误写为赋值符号”=”,是一种容易出现的错误,而且不容易检查出来。来看一个示例程序page6_7.c,其代码如下:

 1#include <stdio.h>
2
3int main()
4{
5 int i, j;
6 i = 10;
7 j = 20;
8 if(i = j)
9 printf("i equal j\n");
10
11 return 0;
12}

编译运行效果如下:

本程序第8行,本意是判断i是否等于j,如果相等则打印语句。现在将”==”误写为”=”,语意变成将j的值赋值给i,然后if判断i的值是否为0。所以,除非j的值为0,否则第8行的if判断总是为真。做为验证,可以试试下面的程序运行效果:

 1#include <stdio.h>
2
3int main()
4{
5 int i, j;
6 i = 10;
7 j = 0;
8 if(i = j)
9 printf("i equal j\n");
10
11 return 0;
12}

陷阱2 词法分析中的“贪心法”

C语言中的某些符号,例如/、*、和=,只有一个字符长,称为单字符符号,还有一些符号,例如/*和==,包含多个字符,称为多字符符号。当C编译器读入一个字符”/”后又读入一个字符”*”,那么编译器就必须做出判断:是将其作为两个单字符符号对待还是合起来作为一个字符对待。

C语言对这个问题的解决方案是采用“贪心法”(又称“大嘴法”):每个符号应该包含尽可能多的字符。

看例子page8_9.c,代码如下:

1#include <stdio.h>
2
3int main()
4{
5 int a = 10, b=2;
6 printf("a = 10, b = 2, a---b = %d\n", a---b);
7
8 return 0;
9}

编译执行结果如下:

第6行,a---b按照贪心法分析,等价于(a--) - b,特别需要注意前面是a--,即先取a的值,再做减1操作,所以10 - 2 = 8。没运行之前,我认为结果应该是7呢。

陷阱3 整型常量

如果一个整型常量的第一个字符是数字0,那么该常量将被视作八进制数,因此,11和011的含义截然不同。

看代码page10_11.c:

1#include <stdio.h>
2
3int main()
4{
5 int a = 11, b = 011;
6 printf("a = %d, b = %d\n", a, b);
7
8 return 0;
9}

编译执行结果如下:


由执行结果可以看出,011被看作是八进制数,对应的十进制数是9。

陷阱4 字符与字符串

C语言中的单引号与双引号含义迥异,在某些情况下,如果把两者弄混,编译时会出错,有时编译器不报错,从而在运行时产生难以预料的结果。

用单引号括起来的一个字符实际上代表一个整数,整数值对应于该字符在编译器采用的字符集中的序列值。因此,对于采用ASCII字符集的编译器而言,’a’的含义与0141(八进制)或者97(十进制)严格一致。

用双引号括起来的字符串,代表的却是一个指向无名数组起始字符的指针,该数组被双引号之间的字符以及一个额外的二进制值为0的字符’\0’初始化。

下面这个语句:

printf(“Hello world\n”);

char hello[] = {‘H’, ‘e’, ‘l’, ‘l’, ‘o’, ‘ ‘, ‘w’, ‘o’, ‘r’, ‘l’, ‘d’, ‘\n’, 0};

printf(hello);

是等效的。

C陷阱与缺陷代码分析之第1章词法陷阱的更多相关文章

  1. C陷阱与缺陷代码分析之第2章语法陷阱

    作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz 陷阱1 理解函数声明 作者提出一个问题:有一个首地址为0的函数,该函数返回值类型为void,没有参数.怎样用C语言的 ...

  2. [C陷阱和缺陷] 第1章 词法“陷阱”

    有感自己的C语言在有些地方存在误区,所以重新仔细把"C陷阱和缺陷"翻出来看看,并写下这篇博客,用于读书总结以及日后方便自身复习. 第1章 词法"陷阱" 1.1 ...

  3. c缺陷与陷阱笔记-第一章 词法陷阱

    1.运算符的贪心性,匹配最长的运算符,例如 n-->0,从-开始,-是运算符,--是运算符,-->就不是,所以是 n -- > 0,--是 a---b,-是,--是,,---不是,所 ...

  4. 《C陷阱与缺陷》 第0章导读 第1章词法陷阱

    1.= 与==的区别 赋值运算符= 的优先级要小于逻辑运算符== 也就是说,会进行先逻辑上的比较,然后再把比较结果进行赋值,很合理. getc库是什么??? 1.C语言中有单字符 = 也有多字符单元如 ...

  5. C语言学习书籍推荐《C陷阱与缺陷》下载

    下载地址:点我 凯尼格 (作者), 高巍 (译者) <C和C++经典著作:C陷阱与缺陷>适合有一定经验的C程序员阅读学习,即便你是C编程高手,<C和C++经典著作:C陷阱与缺陷> ...

  6. 阅读《C陷阱与缺陷》的知识增量

    版权声明:本文为Focustc原创文章.转载请注明作者及出处. https://blog.csdn.net/caozhankui/article/details/35925939 看完<C陷阱与 ...

  7. C陷阱与缺陷(一)

    第一章 词法陷阱 术语“符号”指的是程序的一个基本组成单元,其作用相当于一个句子中的单词.编译器中负责将程序分解为一个一个符号的部分,一般称为“词法分析器”. 1.1 =不同于== 一般容易将比较运算 ...

  8. 我的《C陷阱与缺陷》读书笔记

    第一章 词法“陷阱” 1. =不同于== if(x = y) break; 实际上是将y赋给x,再检查x是否为0. 如果真的是这样预期,那么应该改为: if((x = y) != 0) break; ...

  9. 《C陷阱与缺陷》杂记

    第一章 词法"陷阱" 1.4整型常量 如果一个整型常量的第一个字符是数字0,那么该常量将被视作八进制数.因此,10与010的含义截然不同.需要注意这种情况,有时候在上下文为了格式& ...

随机推荐

  1. Visual Studio 创建和使用dll的方法

    DLL是一个包含可由多个程序同时使用的代码和数据的库. DLL文件就是把一些函数导出来,然后在新程序中进行复用的过程. 第一部分:使用Visual Studio 2010进行DLL的制作 生成方法一: ...

  2. php下正则表达式整理

    一.正则表达式的历史背景 1,内容深厚的正则表达式 ^.+@.+\\..+$ 形式 字符串搜索与匹配的工具 2,应用范围 手机输入法 Windows文件搜索 linux 列出文件命令 网站用户注册,如 ...

  3. Qt中所有类型之间的转换

    1.char * 与 const char *的转换 char *ch1="hello11";const char *ch2="hello22";ch2 = c ...

  4. JavaScript自调用匿名函数

    Self-Invoking Anonymous Function,即自调用匿名函数.顾名思义,该函数没有名称,不同的是,该函数定义后立即被调用.该函数的作用是在应用中初始化或做一次性工作. 普通匿名函 ...

  5. WM_PAINT消息小结

    WM_PAINT是Windows窗口系统中一条重要的消息,应用程序通过处理该消息实现在窗口上的绘制工作. 1. 系统何时发送WM_PAINT消息? 系统会在多个不同的时机发送WM_PAINT消息:当第 ...

  6. 函数可以作为Javascript对象(哈希表)的键吗

    一般Javascript书在讲解对象时,都指出Javascript中的对象可以作为哈希表,存储键值数据.通常情况下,键为字符串,如果键是数字的话,实际上在内部也会转换为字符串. 比如 var o = ...

  7. leetcode第一刷_Binary Tree Inorder Traversal

    递归实现当然太简单,也用不着为了ac走这样的捷径吧..非递归实现还挺有意思的. 树的非递归遍历一定要借助栈,相当于把原来编译器做的事情显式的写出来.对于中序遍历,先要訪问最左下的节点,一定是进入循环后 ...

  8. css3处理sprite背景图压缩来解决H5网页在手机浏览器下图标模糊的问题

    近期在负责一个微信H5 App项目,遇到一个郁闷的问题,手机浏览器查看网页时图标都是模糊的,有锯齿,电脑浏览器显示则是正常.大概知道是分辨率适配等类型的问题,后来网上查找了一些办法.大部分的解决方式都 ...

  9. Android 蓝牙( Bluetooth)耳机连接分析及实现

    Android 实现了对Headset 和Handsfree 两种profile 的支持.其实现核心是BluetoothHeadsetService,在PhoneApp 创建的时候会启动它. if ( ...

  10. 不能使用ASP.NET验证控件---WebForms UnobtrusiveValidationMode 需要“jquery”ScriptResourceMapping。请添加一个名为 jquery (区分大小写)的 ScriptRes

    方法一: 在webconfig中找到 <appSettings>        <add key=" aspnet:UseTaskFriendlySynchronizati ...