第十章编译预处理与位运算.ppt
第第10章章 编译预处理与位运算编译预处理与位运算 10.1 编译预处理编译预处理编译预处理编译预处理:是在编译前由编译系统中的预处理程序对源程序是在编译前由编译系统中的预处理程序对源程序的预处理命令进行加工。的预处理命令进行加工。源程序中的预处理命令均以源程序中的预处理命令均以“#”开头开头,命令,命令末尾不加分号末尾不加分号,它们可以写在程序中的任何位置,它们可以写在程序中的任何位置,作用域作用域是从出现位置开始到是从出现位置开始到源程序的结束源程序的结束.10.1.1 宏定义宏定义宏定义是定义一个标识符来代替一个字符串。宏定义是定义一个标识符来代替一个字符串。宏定义有不带参数的宏定义和带参数的宏定义两种。宏定义有不带参数的宏定义和带参数的宏定义两种。1不带参数的宏定义不带参数的宏定义定义形式:定义形式:#define 标识符标识符 字符串字符串功能:用一个指定的标识符(即名字,称为宏名)来代表一个字符功能:用一个指定的标识符(即名字,称为宏名)来代表一个字符串。串。例如:例如:#define PI 3.1415926说明:说明:(1)与其他标识符相区别,宏名一般用大写字母表示。)与其他标识符相区别,宏名一般用大写字母表示。(2)编译预处理时,将程序中的宏名用字符串代替,这种将宏名替)编译预处理时,将程序中的宏名用字符串代替,这种将宏名替换成字符串的过程称为换成字符串的过程称为“宏展开宏展开”。(3)使用宏可以减少程序中重复书写或修改某些字符串的工作量)使用宏可以减少程序中重复书写或修改某些字符串的工作量.(4)在程序中出现在双引号中或其他字符串中与宏名相同的字符串,)在程序中出现在双引号中或其他字符串中与宏名相同的字符串,不能作为宏处理。不能作为宏处理。(5)#define命令的作用范围从定义位置至源程序结束,但可以用命令的作用范围从定义位置至源程序结束,但可以用#undef终止其作用域终止其作用域。例例1:#define PI 3.1415926main()float l,s,r;scanf(%d,&r);l=2.0*PI*r;s=PI*r*r;printf(l=%fn,l);printf(s=%fn,s);main()float l,s,r;scanf(%d,&r);l=2.0*3.1415926*r;s=3.1415926*r*r;printf(l=%fn,l);printf(s=%fn,s);展开10.1.1 宏定义宏定义例例2:#define PI 3.1415926main()#undef PIfun()10.1.1 宏定义宏定义10.1.1 宏定义宏定义(6)宏定义时,可以引用已定义的宏名,编译时)宏定义时,可以引用已定义的宏名,编译时层层展开层层展开。例例3:#define PI 3.1415926#define R 3.0#define L 2*PI*R#define X R+Lmain()y=2*X;main()y=2*3.0+2*3.1415926*3.0;展开(7)宏名是一个常量标识符宏名是一个常量标识符,不是变量,不分配内存空间。,不是变量,不分配内存空间。2带参数的宏定义带参数的宏定义定义形式:定义形式:#define 标识符标识符(参数表参数表)字符串字符串功能:用指定的带参数的标识符来代表一个字符串。功能:用指定的带参数的标识符来代表一个字符串。注意:带参数的宏展开时要用实参字符串替换形参字符串。注意:带参数的宏展开时要用实参字符串替换形参字符串。例例4:#define S(x)2*x*xmain()y=S(2+2);main()y=2*2+2*2+2;展开注意注意:展开时用实参字符串:展开时用实参字符串2+2替换形参字符串替换形参字符串x,2+2是字符串,是字符串,不能看做表达式,即不能看做表达式,即S不能展开为不能展开为2*(2+2)*(2+2)。10.1.1 宏定义宏定义10.1.2 文件包含文件包含文件包含是一个源程序通过文件包含是一个源程序通过#include命令把另外一个文命令把另外一个文件的全部内容嵌入到源程序中。件的全部内容嵌入到源程序中。文件包含命令有如下两种格式:文件包含命令有如下两种格式:#include#include文件名文件名功能:将指定文件的全部内容放到该命令行所在的位置。功能:将指定文件的全部内容放到该命令行所在的位置。说明:命令说明:命令#include在搜索文件时只检索在搜索文件时只检索C语语言编译系统所确定的标准目录,而命令言编译系统所确定的标准目录,而命令#include文件文件名名在搜索文件时首先对使用包含文件的源程序文件所在搜索文件时首先对使用包含文件的源程序文件所在的目录进行检索,若没有找到指定的文件,再在标在的目录进行检索,若没有找到指定的文件,再在标准目录中检索。准目录中检索。10.2 位运算数据在计算机内部是以二进制补码形式存储的。数据在计算机内部是以二进制补码形式存储的。1按位与运算符:&若参与运算的两个操作数对应的两个二进制位都是若参与运算的两个操作数对应的两个二进制位都是1,则,则对应位结果为二进制位对应位结果为二进制位1,否则为,否则为0。例例1:求:求5&3的值。的值。运算过程如下:运算过程如下:0000 0000 0000 0101(5的补码)的补码)&0000 0000 0000 0011(3的补码)的补码)0000 0000 0000 0001 (1的补码,即的补码,即5&3=1)2按位或运算符:|若参与运算的两个操作数对应的两个二进制位有一个为若参与运算的两个操作数对应的两个二进制位有一个为1,则对应位结果为二进制位,则对应位结果为二进制位1,否则为,否则为0。例例2:求:求5|3的值。的值。运算过程如下:运算过程如下:0000 0000 0000 0101(5的补码)的补码)|0000 0000 0000 0011(3的补码)的补码)0000 0000 0000 0111(7的补码,即的补码,即5|3=7)10.2 位运算位运算3按位异或运算符:若参与运算的两个操作数对应的两个二进制位相异(一若参与运算的两个操作数对应的两个二进制位相异(一个为个为1,另一个为,另一个为0),则对应位结果为二进制位),则对应位结果为二进制位1,否则为否则为0。例例3:求:求53的值。的值。运算过程如下:运算过程如下:0000 0000 0000 0101(5的补码)的补码)0000 0000 0000 0011(3的补码)的补码)0000 0000 0000 0110(6的补码,即的补码,即53=6)10.2 位运算位运算4按位取反运算符:“”的操作数只有一个,若操作数的某二进制位为的操作数只有一个,若操作数的某二进制位为1,则对应位结果为则对应位结果为0,若操作数的某二进制位为,若操作数的某二进制位为0,则对,则对应位结果为应位结果为1,例例4:求:求5的值。的值。运算过程如下:运算过程如下:0000 0000 0000 0101(5的补码)的补码)1111 1111 1111 1010(-6的补码,即的补码,即5=-6)10.2 位运算位运算5左移运算符:左移运算的一般形式为:左移运算的一般形式为:操作数操作数 移位位数移位位数功能:将一个操作数的所有二进制位依次左移若干位,高位移出并功能:将一个操作数的所有二进制位依次左移若干位,高位移出并舍弃,低位补舍弃,低位补0。例例5:求:求53的值。的值。运算过程如下:运算过程如下:0000 0000 0000 0101(5的补码)的补码)3 0000 0000 0000 0101000(40的补码,即的补码,即5左移运算的一般形式为:左移运算的一般形式为:操作数操作数 移位位数移位位数功能:将一个操作数的所有二进制位依次右移动若干位。若操作数功能:将一个操作数的所有二进制位依次右移动若干位。若操作数为无符号数或正数,移出的低位被舍弃,高位补为无符号数或正数,移出的低位被舍弃,高位补0。这种移位操。这种移位操作又称逻辑右移。若操作数为有符号数的负数,即最高位为作又称逻辑右移。若操作数为有符号数的负数,即最高位为1时,时,右移时高位补右移时高位补1,以保持符号位不变,低位移出并舍弃。这种移,以保持符号位不变,低位移出并舍弃。这种移位操作又称算术右移。位操作又称算术右移。例例6:求:求51的值。的值。运算过程如下:运算过程如下:0000 0000 0000 0101(5的补码)的补码)1 0000 0000 0000 00100(2的补码,即的补码,即51=2)10.2 位运算位运算7位运算应用举例例例10.1 取一个整数取一个整数a从右端开始的第从右端开始的第47位。位。程序如下:程序如下:#includemain()unsigned a,b,c,d;scanf(%o,&a);b=a4;c=(04);d=b&c;printf(%o,%dn%o,%dn,a,a,d,d);10.2 位运算位运算10.3 本章考点n宏定义。宏定义。n文件包含。文件包含。n位运算。位运算。10.4 典型试题详解1有如下程序:有如下程序:#define N 2#define M N+1#define NUM 2*M+1main()int i;for(i=1;i=NUM;i+)printf(%dn,i);该程序中的该程序中的for循环执行的次数是循环执行的次数是_。正确答案:正确答案:6(知识点:不带参数的宏定义)(知识点:不带参数的宏定义)2程序中头文件程序中头文件type1.h的内容是:的内容是:#define N 5#define M1 N*3程序如下:程序如下:#include type1.h#define M2 N*2main()int i;i=M1+M2;printf(%dn,i);程序编译后运行的输出结果是程序编译后运行的输出结果是_。正确答案:正确答案:25(知识点:文件包含、不带参数的宏定义)(知识点:文件包含、不带参数的宏定义)10.4 典型试题详解3以下程序的输出结果是以下程序的输出结果是_。#define SQR(X)X*Xmain()int a=16,k=2,m=1;a/=SQR(k+m)/SQR(k+m);printf(%dn,a);正确答案:正确答案:2(知识点:带参数的宏定义)(知识点:带参数的宏定义)10.4 典型试题详解典型试题详解4有以下程序:有以下程序:main()int x=3,y=2,z=1;printf(%d n,x/y&z);程序运行后的输出结果是程序运行后的输出结果是_。A)3 B)2 C)-1 D)0正确答案:正确答案:D(知识点:位运算)(知识点:位运算)10.4 典型试题详解5有以下程序:有以下程序:main()unsigned a,b,c;a=0 x3;b=a|0 x8;c=b1;printf(%d%d n,b,c);程序运行后的输出结果是程序运行后的输出结果是_。A)-11 12B)-6 13C)12 24D)11 22正确答案:正确答案:D(知识点:位运算)(知识点:位运算)