Presentation is loading. Please wait.

Presentation is loading. Please wait.

第二章 C的基本数据类型及运算 2.1 标识符 2.2 数据类型 2.3 常量 2.4 变量 2.5 运算符 2.6 表达式

Similar presentations


Presentation on theme: "第二章 C的基本数据类型及运算 2.1 标识符 2.2 数据类型 2.3 常量 2.4 变量 2.5 运算符 2.6 表达式"— Presentation transcript:

1 第二章 C的基本数据类型及运算 2.1 标识符 2.2 数据类型 2.3 常量 2.4 变量 2.5 运算符 2.6 表达式
2.7 数据类型, 运算符与表达式举例

2 2.1 标 识 符 正确 不正确 count 1 count test123 hi!there
正确 不正确 count count test hi!there High-balance high..balance PI a+b

3 说明:  (1) 与有些程序设计语言的规定不同, 在C语言中, 标识符中大小写字母是有区别的。程序中基本上都采用小写字母表示各种标识符,如变量名、数组名、函数名等。书写的各种语句也均用小写字母,而大写字母只用来定义宏名等,用的不多。  (2) 不同的系统对标识符的长度有不同的要求, 有的要求为6个字符,有的允许使用8个字符,而Turbo C系统下的有效长度为1至32个字符。  (3) 除了少数工作单元我们用单个字符作标识符,一般的应做到见名知意,以提高程序的可读性。如用sum表示和, score表示成绩, max表示最大等等。

4 2.1.2 关键字 ANSI C规定了32个关键字(保留字),不能再用作各种标识符。下面列出32个关键字:auto, break, case, char, const, continue, default, do, double, else, enum, extern, float, for, goto, if, int, long, register, return, short, signed, sizeof, static, struct, switch, typedef, union, unsigned, void, volatile, while。  它们用来表示C语言本身的特定成份, 具有相应的语义, 可构成所有的C语言语句。  C语言还使用下列12个标识符作为编译预处理的命令单词, 但使用时前面应加“#”: define, elif, else, endif, error, if, ifdef, ifndef, include, line, progma, undef。

5 2.2 数据类型

6 2.2.1 基本数据类型 1. 基本数据类型 表 2.1 C基本数据类型的长度和值域

7 字符型(char)变量用于存贮ASCII码字符,也可存贮8位二进制数。 
整型(int)变量用于存贮整数。因其字长有限,故可表示的整数的范围也有限。  单精度实型(float)和双精度实型(double)变量用于存贮实数,实数具有整数和小数两部分或是带指数的数据。表中的值域用绝对值表示。  无值型(void)有两种用途:第一是明确地表示一个函数不返回任何值;第二是产生同一类型的指针。

8 2. 类型修饰符 除了无值类型外, 基本数据类型可以带有各种修饰前缀。修饰符用于明确基本数据类型的含义,以准确地适应不同情况下的要求。类型修饰符种类如下:  signed 有符号 unsigned 无符号 long 长 Short 短

9 表 2.2 C基本类型及其修饰符的所有组合

10 不同的计算机系统对各类数据所占内存字节数有不同的规定,如int型有的系统占16位,有的占32位。long double型有的占128位,有的占64位。 
有符号(signed)和无符号(unsigned)的整型量的区别在于它们的最高位的定义不同。如果定义的是有符号的整型(signed int),C编译程序所产生的代码就设定整型数的最高位为符号位,其余位表示数值大小。如最高位为0,则该整数为正;如最高位为1,则该整数为负。例如用8位二进制表示时:

11 大部分计算机表示有符号数时都使用二进制补码。原因及细节将在微机原理课上学习。补码的求法很简单:正数补码即原码;负数的补码是将其对应原码的各位(除符号位外)按位求反,然后加1。上述四个数用 8 位二进制表示有符号数时机内补码值为:

12 有符号整数对于许多运算都是很重要的。但是它所能表达的最大数的绝对值只是无符号数的一半。例如,32767的有符号整数表示为: 
如果最高位设置为1,则该数就会被当作-1。然而,如将该数定义为无符号整型(unsigned int),那么当最高位设置为1时,它就变成了65535。

13 3. 访问修饰符 C语言有两个用于控制访问和修改变量方式的修饰符, 它们分别是常量(const)和易变量(volatile)。  带const修饰符定义出的常量在程序运行过程中始终保持不变。 例如:  const int num;  将产生整型常量num,其值不能被程序所修改, 但可以在其它类型的表达式中使用。const型量可以在其初始化时直接被赋值, 或通过某些硬件的方法赋值,例如num要定义成100, 可写成:  const int num=100;  以后程序中出现num的地方就是100, 也不能再被改变。

14 volatile修饰符用于提醒编译程序, 该变量的值可以不通过程序中明确定义的方法来改变。例如一个全程变量用于存贮系统的实时时钟值, 在这种情况下,变量的内容在程序中没有明确的赋值语句对它赋值时,也会发生改变。这一点是很重要的,因为在假定表达式内变量内容不变的前提下,C编译程序会自动地优化某些表达式,有的优化处理将会改变表达式的求值顺序。 修饰符volatile就可以防止上述情况发生。  const和volatile可以同时使用。例如,假设0x30是一个只随外部条件而变化的口地址值,那么就恰好需要用下述说明来避免偶然因素所产生的副作用的影响。  const volatile unsigned char *port=0x30;

15 2.2.2 构造数据类型 数组是一组连续、有序的存放在一起的具有相同类型的数据。
结构体是将不同类型的数据按一定顺序存放在一起的数据结构。  共用体是将不同类型的数据都存放在同一起始地址的内存单元中, 共用一段内存以节省内存单元。  枚举是只有几种可能的值,将其一一列举出来。实际是用符号来表示若干个可取的整型值, 它是整型的一个子集。

16 2.2.3 指针类型 指针是C语言中一个重要概念。正确而灵活地运用它,可以有效地表示复杂的数据结构;能动态分配内存;能方便地使用字符串;有效而方便地使用数组; 在调用函数时能得到多于一个的值;能直接处理内存地址等。  指针类型迥异于前述各种数据类型,不管是简单类型的数据,还是构造类型数据,均是代表数据的,而指针类型是代表地址的。

17 2.3 常 量 2.3.1 数值常量 1. 整型常量 整型常量也称为整型常数或整数。 
2.3 常 量 2.3.1 数值常量 1. 整型常量 整型常量也称为整型常数或整数。  C整型常量按进制分可分为十进制整数,八进制整数和十六进制整数。  1) 十进制整数 十进制整数以正负号开头,后跟0~9的若干位数字构成。如123, -456, 0等。

18 2) 八进制整数 八进制整数是以正负号开头,第一位数字一定是0,后面跟0~7的数字。如八进制数0123,相当于十进制数83;八进制数-012,相当于十进制数-10。  八进制数与十进制数的转换,方法如下:  0123=1×82+2×81+3×80= =83

19 3) 十六进制整数 十六进制整数是以正负号开头,前两位为0x,后面跟0~9和a~f的数字。其中a代表10, b代表11, 其余类推。 如十六进制数0x123,相当于十进制数291;十六进制数-0x12,相当于十进制数-18。  十六进制数转换成十进制数,方法如下:  0x123=1×162+2×161+3×160= =291 0x1ab=1×162+10×161+11×160= =427

20 4) 二进制数, 字节, 字, 位计算机内所有的信息均用二进制表示,即计算机内只有0和1,也只认识由0和1组成的程序或数据。为什么在计算机中要使用二进制数呢? 因为二进制数运算规则简单,用物理器材容易实现,如电压的高与低, 开关的开与关,脉冲的有与无等等。  一个二进制数0或1, 称为“位”(bit)。 在计算机存贮器中,为了便于管理,常将 8 个位称为一个“字节”(byte),每个字节存放在一个存贮单元中,每个单元赋于一个存贮地址。  计算机在处理数据时,每一个数据是一个“字”(word),字是由若干字节组成。字可以是1个字节(字符),2个字节(整数),4个字节(实数,长整型数),8个字节(双精度实数)等等。

21 2. 单精度实型常量 1) 小数形式 一个实数可以是正负号开头,有若干位0~9的整数,后跟一个小数点(必须有),再有若干位小数部分。如 , 。 数12用实数表示必须写成12.0或12.。  一个实数有数值范围和有效位数的限制。实数的数值范围是3.4×10-38≤|x|≤3.4×1038,当小于3.4×10-38时按0对待(下溢), 而大于3.4×1038时则上溢,一个溢出的数是无意义的。实数仅有7位有效数字,超过七位的将是不精确的。 如 ,在计算机内仅保留为 ,第八位数无法保留而失去,并不是第八位向第七位四舍五入。当上面的数要求用小数五位表示时,则表达为 ,即第七位向第六位四舍五入。

22 2) 指数形式 实数的指数形式也称为科学计数法。一个实数的指数形式分成尾数部分和指数部分。尾数部分可以是整数形式或小数形式,指数部分是一个字母“e”后跟一个整数。如123e+01, e-01, 0e0等。由于实数仅有7位有效数字,因此在内存中用三个字节来表示尾数, 用一个字节来表示指数,所以指数部分用两位整数来表示。 在书写时“e”与“E”完全等价。“e”前面必须有数字,“e”后面必须是整数。

23 3. 双精度常量 当一个数用实数表达时,仅有七位有效数字,用长整型表达时仅有十位有效数字,实数的数值范围也只能小于3.4×1038。 当超过以上范围时,我们可以用双精度常量来表达。  双精度常量的取值范围由1.7×10-308≤|x|≤1.7×10308,有效位可达16位左右。一个数当超过长整型数表达范围或超过实数表达范围时均按双精度常量对待。一个双精度常量在内存中占8个字节。  长双精度常量取值范围在 ~104932之间,有19位有效数字,在内存中占16个字节。但它是由计算机系统决定的, 在Turbo C中,与double型一致。

24 2.3.2 字符常量 表 2.3 控制字符表示法

25 2.3.3 字符串常量

26 符号常量 1. 不带参数的宏定义 宏定义命令#define用来定义一个标识符和一个字符串,在程序中每次遇到该标识符时就用所定义的字符串替换它。这个标识符叫做宏名,替换过程叫做宏替换或宏展开。宏定义命令#define的一般形式是:  #define 宏名 字符串

27 例如你想用PI表示数值3.14159, 可以用宏定义#define来说明: 
#define PI  这样在编译时,每当在源程序中遇到PI就自动用 代替,这就是宏展开。  若定义了一个宏名, 这个名字还可以做为其它宏定义的一个部分来使用。 例如:  #define PI  #define PI2 2*PI 则在程序中出现的“PI2”处被“2* ”来替换。 

28 应注意宏替换仅是简单地用所说明的字符串来替换对应的宏名,无实际的运算发生,也不作语法检查。例如:
#define PI ;  … area=PI*r*r; 经过宏替换后, 该语句展开为 area= ; *r*r;  然后经编译将出现语法错误。

29 在C语言程序中习惯上用大写字母作为宏名。
#undef 宏名 来终止其作用域。 例如:  #define PI  main( ) { … } #undef PI f1( )

30 例 2.1 宏定义的使用。  程序: #define R 3.0 #define PI 3.1415926
例 2.1 宏定义的使用。  程序: #define R  #define PI  #define L 2*PI*R #define S PI*R*R main( ) { printf(″L=%f\n S=%f\n″, L, S); } 运行情况如下:  L=  S=  经过宏展开后, printf函数调用语句被展开为:  printf(″L=%f\n S=%f\n″, 2* *3.0, *3.0*3.0);  而在双引号内的L, S将不被替换, 即字符串内与宏名相同的部分将不替换。

31 2. 带参数的宏定义 它不是进行简单的字符串替换, 还要进行参数替换。 其定义的一般形式为:  #define 宏名(参数表) 字符串 其中字符串中包括参数表中所指定的参数。 在使用时, 要将程序中宏名后的实际参数代入字符串中参数的位置。 例如:  #define S(a, b) a*b … area=S(3, 2);  经编译预处理, 该语句被展开成 area=3*2;

32 说明:  (1) 宏名和参数表左括号之间不能有空格, 否则按不带参宏替换了。  (2) 字符串中应注意括号的使用,以保证运算次序。如上例改成 area=S(1+2, 2);  经展开后变成 area=1+2*2;  这就不合我们的要求了。 此时, 可改写成  #define S(a, b) (a)*(b) … area=S(1+2, 2) 经展开后变成  area=(1+2)*(2);  就不会出现错误了。

33 2.4 变 量 2.4.1 变量的定义 1. 变量定义 变量定义的一般形式如下:  类型 变量名表; 
2.4 变 量 2.4.1 变量的定义 1. 变量定义 变量定义的一般形式如下:  类型 变量名表;  这里,类型(type)必须是C语言的有效数据类型。变量名表可以是一个或多个标识符名,中间用逗号分隔,最后以分号结束。以下是一些变量定义的例子:  int i, j, num;  float a, b, sum;  unsigned int ui;  char c, ch, name;  double x, total;

34 2. 说明 (1) 变量名可以是C语言中允许的合法标识符, 用户定义时应遵循“见名知意”的原则,以利于程序的维护(今后所有标识符均如此,不再重复)。  (2) 每一个变量都必须进行类型说明,这样就可以保证程序中变量的正确使用。未经类型说明的变量在编译时将被指出是错误的,也就是变量要先定义,后使用。  (3) 当一个变量被指定为某一确定类型时,将为它分配若干相应字节的内存空间。如char型为1字节,int型为2字节,float为4字节,double为8字节。当然,不同的系统可能稍有差异。

35 (4) 变量可以在程序内的三个地方定义: 在函数内部, 在函数的参数(形参)定义中或在所有的函数外部。由此定义的变量分别称为局部变量, 形式参数和全局变量。在不同地方定义的变量,其作用范围不同。在同一层次定义的变量,不能与数组、指针、函数和其它变量同名。  (5) 变量是用来存放数据的,由于数据有不同的类型,因此要定义相应类型的变量去存放它。这些数据称为相应变量的值。

36 2.4.2 C语言中各种类型的变量 1. 整型变量 整型变量用来存放整型数值。整型变量可分为:基本型(int), 短整型(short int或short),长整型(long int或long)和无符号型(unsigned int, unsigned short, unsigned long)。  前三种整型变量存贮单元的最高位为符号位。0表示为正,1表示为负。无符号型变量存贮单元的所有位均表示数值。具体可参看表2.2。  在使用整型变量时一定要注意数值的范围,超过该变量允许的使用范围将导致错误的结果。

37 2. 实型变量 实型变量分为单精度型(float)和双精度型(double)两类。其存放数据的差别是:单精度变量占4个字节内存单元,有7位有效数字,数值范围在3.4e-38~3.4e+38之间。而双精度变量占有8个字节内存单元,有15~16位有效数字,数值范围在1.7e-308~1.7e+308之间。

38 3. 字符型变量 字符型(char)变量内存放字符型常量, 在内存单元中仅占一个字节。 其内存中存放的是该字符的ASCII码, 因此字符型变量也可存贮数值范围为0~255或-128~127之间的整型常数。  在C语言中,字符型与整型的界限不是很分明的,在一个字节内是可互相转换的。

39 4. 枚举型变量 枚举型是一个整型常量的集合。这些常量指定了所有该类型变量可能具有的各种合法值。枚举在我们日常生活中十分常见。例如,星期的枚举为:{星期日, 星期一, 星期二,星期三,星期四,星期五,星期六}。  枚举的定义形式是:  enum 〈枚举类型名〉 {枚举元素表} 〈变量表〉;

40 其中枚举类型名和枚举变量表是选择项。 下面我们来看一个枚举类型的定义和变量定义的例子: 
enum weekday {sun, mon, tue, wed, thu, fri, sat};  enum weekday workday, restday;  其中第一句是定义枚举类型enum weekday, weekday是枚举类型名,而花括号内是该枚举型变量可能具有的各种情况的一一列举。第二句是定义枚举型变量,即变量workday, restday是属于enum weekday枚举类型的,该枚举型变量只能赋予花括号内的常量,例如: workday=mon; restday=sun;

41 枚举类型的定义和变量的定义有三种形式: 
(1) 上面举例即是, 即枚举类型和枚举变量是分别定义的。 (2) 可将上述形式合并成一句:  enum weekday {sun, mon, tue, wed, thu, fri, sat} workday restday;  (3) 当只有一种枚举类型时, 可省略枚举类型名:  enum {sun, mon, tue, wed, thu, fri, sat} workday, restday;

42 具体的枚举元素对应的整数由两种情况决定: 
(1) 缺省:当花括号内的枚举元素没有被初始化, 第一项代表整数0,第二项代表整数1,以此类推。  (2) 初始化:我们可以用初始化来改变枚举元素的相应值。 例如: enum weekday {mon=1, tue, wed, thu, fri, sat, sun} workday, restday;  在上句中,mon代表1,后面仍然自动增1,即tue代表2,sat代表6,而sun在此不代表0而代表7。 初值可以从任何一个整数开始,也可以指定几个初值,也可给任何一个枚举常量赋初值。 例如:

43 enum weekday {sun, mon, tue, wed=5, thu, fri, sat}; 
此后sum为7, mon为1, tue为2, wed为3, thu为4, fri为5, sat为6。  枚举型变量值在输出时是输出其整常数而不是其枚举元素的标识符。 枚举型变量在赋值时可以赋枚举元素而不能直接赋整型常量, 如要赋整型常量,则要进行类型转换。例如: restday=(enum weekday) 6; 或 restday=sat;

44 例 2.2 打印出枚举元素sat的内存值。 程序:  main( ) { enum{ sun, mon, tue, wed, thu, fri, sat} workday, restday;  restday=sat;  printf(″restday is %d\n″, restday);  } 运行:  restday is 6

45 5. 其它类型变量 C语言中无字符串变量,但可以用字符数组或字符型指针来表达字符串。另外还有指针型变量,结构体型变量, 共用体型变量等, 这些将在后续章节中介绍。 C语言中没有逻辑型变量, 所有非零数值被认为是逻辑“真”, 而数值零被认为是逻辑“假”。无值型类型一般不用来说明变量, 只用在函数或指针中。

46 2.4.3 变量的初始化 程序中常需要对一些变量预先设置初值。 C规定, 可以在定义变量时同时使变量初始化。变量初始化只需定义变量时在变量名后面加一等号及一个常数。它的一般形式是:  类型 变量名=常数;  以下是几个示例:  char ch=′a′;  int first=0;  float x=123.45;

47 2.5 运 算 符 (1) 算术运算符(+, -, *, /, %, ++, --)。
(2) 关系运算符(<, >, <=, >=, ==, ![KG-*8]=)。 (3) 逻辑运算符(!, &&, ||)。 (4) 位运算符(<<, >>, ~, |, ^, &)。 (5) 赋值运算符(=, 及其双目运算符的扩展赋值运算符)。 (6) 条件运算符(? :)。 (7) 逗号运算符(,)。 (8) 指针运算符(*, &)。 (9) 求字节数运算符(sizeof)。 (10) 强制类型转换运算符((类型))。 (11) 分量运算符(·, ->)。 (12) 下标运算符([ ])。 (13) 圆括号运算符(( ))。

48 2.5.1 算术运算符和赋值运算符 表 2.4 算术运算符和赋值运算符

49 说明:  (1) +, -, *, / 与数学中运算类似, 先乘除后加减, 也就是按优先级顺序进行运算,优先级小的先运算。要改变运算顺序只要加括号就可以了,括号全部为圆括号,必须注意括号的配对,它们适用于C的几乎全部数据类型(指针类除外)的各种运算(++, --除外)。除法运算符(/)在用于两个整型数据运算时,其运算结果也是整数,余数总是被截掉。如1/2的结果是0;10/3的结果是3。

50 (2) 求余运算符(%)仅用于整型数据,不能用于实型和双精度实型。它的作用是取整数除法的余数。如1%2的结果是1; 10%3的结果也是1。 
(3) 赋值运算符(=)是将右边表达式的值赋给左边的变量。 赋值运算符左边必须是变量等有存贮单元的元素,而不能是常量或表达式。如x=x+1是合法的,即把x的值加上1后再赋给x,而x+1=x却是非法的,因为x+1不是一个存贮单元, 不能被赋以值。赋值号有别于数学中的等号,这一点是要注意的。

51 (4) ++, --仅用于整型变量,指针变量。用于整型变量在原值上加1或减1;用于指针变量是取下一地址或上一地址。 关于指针部分的使用在第八章中介绍。 增1和减1运算符用在表达式中时,写法是有差别的:如果运算符在操作数前面, 则在表达式“引用”该操作数前,先对其作加1或减1运算; 如果运算符在操作数之后,则先“引用”该操作数,然后再对它作加1或减1运算。考虑以下程序:

52 main( ) { int x, y;  x=10;  y=++x; printf(″%d, %d\n″, x, y);  } 运算结果为  11, 11 此时y的值和x的值都为11。 然而换一种写法:  y=x++; 运行结果为  11, 10

53 此时y的值是10,而x的值自增后为11。上述两种情况x都变成了11,而y的值却不同。它们的差别只在于给x加1的时机不同。 此时赋值即为引用。 再如进行输出操作时,有以下程序段: 
printf(″x=%d\n″, ++x);  运行结果为x=11,执行其下一条语句时x也是11, 而程序段: printf(″x=%d\n″, x++); 

54 (5) +, -, *, /, % 可以与赋值号=组成复合赋值运算符+=, -=, *=, /=, %=。 
如a=a+b可以写成a+=b,a=a*b可以写成a*=b。其余类推。 这样书写简练,运行速度快,也提高了编译效率。

55 2.5.2 关系运算符和逻辑运算符 表 2.5 关系和逻辑运算符

56 说明:  (1) 当关系运算符两边的值满足关系时为真, 返回1; 如不满足关系时为假,返回0。例如:  x=10;  printf(″%d\n″, x>=9); 则输出为1。又如:  x=5;  printf(″%d\n″, x>=9);  则输出为0。  字符比较按其ASCII码值进行, 如′A′<′B′为真。

57 (2) 关系运算符>, >=, <, <=的优先级相同, 如在表达式中同时出现时, 则自左向右顺序运算。而==与
(2) 关系运算符>, >=, <, <=的优先级相同, 如在表达式中同时出现时, 则自左向右顺序运算。而==与! =则优先级低于此四种关系运算符。例如:  printf(″%d\n″, 5>3>1); 运行输出结果为0。因为两个>是同一优先级,5>3的结果为1, 而1>1的关系不满足,所以最后结果为0。又如:  printf(″%d\n″, 1==11<35); 运行输出结果为1。因为<的优先级比==高,则11<35的结果为1,而1==1的关系满足,所以最后结果为1。 

58 (3) 逻辑运算的真值表如下所示,逻辑值用1和0表示。 p q p&&q p||q !p

59 (4) 关系和逻辑运算符的优先级都低于算术运算符(逻辑非
(4) 关系和逻辑运算符的优先级都低于算术运算符(逻辑非!除外)。 如10>1+12完全等价于10>(1+12), 其结果当然是假(即0)。  (5) 在关系和逻辑运算符组成的表达式中, 也可以像算术表达式一样, 用圆括号来改变运算的自然优先次序,如! 1&&0其值为假,因为先执行! 1, 然后才执行&&。然而加上圆括号! (1&&0)后改变了运算顺序,则执行! 0操作结果为1,即其值为真。

60 (6) 在逻辑表达式的求解中,并不是所有的逻辑运算符都被执行,只是在必须执行下一个逻辑运算符才能求出表达式的值时,才执行该运算符。例如: 当两个逻辑量a||b时,当a为真时则不再求b的值, 而取值为真(即1)。 当两个逻辑量a&&b时,当a为假,则同样不再求b的值, 而取值为假(即0)。 同理, a||b||c式中当a为真时, 直接取值为真(即1);a&&b&&c式中当a为假时,直接取值为假(即0)。此时若b, c为赋值表达式,则赋值操作就没有进行。  (7) 逻辑运算的转换。  !(a||b)可写成!a&&!b,而! (a&&b)可写成! a||! b。

61 位运算符 表 2.6 位 运 算 符

62 说明:  (1) 位逻辑运算符&(与AND), |(或OR), ^(异或XOR), ~(反NOT)的真值表如下:  P Q P&Q P|Q P^Q ~P

63 真值表似乎与逻辑运算符&&, ||, !类似, 实质上运算中的对象是不同的。上述真值表中的P,Q是一个二进制位,而不是字节或字。 如3&&4, 即两个真值True相与,结果为1。但3&4却要按位表示, 即 其结果是0。

64 (2) 位逻辑运算符&(与AND) 常用于指定某些位清零。 如使整型变量x清零,只要写成x=x&0就可以了;如果使一个字节的第 8 位表示为奇偶校验位并将其设为0,只要ch&127就可以了。 而要保留某些位,只要这几位和1相与,其它位与0相与即可。 如要求对 保留低4位,我们取 和原数按位相与,即得 。

65 (3) 位逻辑运算符|(或OR) 可用于指定某些位为1。 如要使 的低 4 位全为1, 我们取 和原数按位相或, 即得 。  (4) 位逻辑运算符^(异或XOR)。  ① 使特定位反转,只要将该位与1异或即可。 如 要将低 2 位都反转,我们取 与其按位异或, 即得 。  ② 使某些位保留原值,只要将这些位与0异或即可。如上例中的高6位。

66 ③ 整个数清零,只要本身异或一次即可,即x^x。如x为10011100, 则x^x得0。
④ 交换两个值不用临时变量。如a=3,b=4, 则a=a^b; b=b^a; a=a^b; 即a变成4, b变成3了。 具体请看下列式子:

67 (5) 位逻辑运算符~(反NOT) 是对该运算元素每一位都取反。 如~1在8位二进制数中变成了 而不是0。如我们要指定某数x最后一位为0(偶数), 但又不知该数是1字节(char型),2字节(int型)还是4字节(long型),我们只要做x&~1即可。这常用于不同机器间的程序移植。也可用于加密,对一个数求一次反码就变成密码,再对密码求一次反就变成原数了。

68 (6) 左移运算符<<使变量中的每一位向左移动,移出的最高位将丢失(溢出),而右端补入0。左移表达式的形式为变量名<<移位的位数
例如:a=15,即 ,取a=a<<2后, 即a左移两位,变成 ,即十进制数60。对于无符号数,左移一位相当于乘2,左移 2 位相当于乘4。

69 (7) 右移运算符>>使变量中的每一位向右移动, 移出的最低位将丢失, 而高端补0(正数)。对于负数,即原最高位为1时,右移一位,高端补0称逻辑右移,高端补1称算术右移,这由计算机系统决定。对于Turbo C是采用算术右移, 即移入1。 右移表达式的形式为: 变量名>>移位的位数 例如:a=16, 即 ,取a=a>>2后, 即a右移2位,变为 , 即十进制数4。右移一位相当于除2,右移两位相当于除4。

70 (8) 位运算符中&, |, ^, <<, >>可以与赋值号=组成复合赋值运算符&=, |=, ^=, <<=, >>=。 
如a=a&b可写成a&=b, 其余类推。 凡算术运算符, 位运算符中的二目运算符均可与赋值号“=”组成复合运算符。

71 2.5.4 条件运算符和逗号运算符 1. 条件运算符 运算符的一般形式是:  表达式1 ? 表达式2:表达式3
其含义是: 先求表达式1的值,如果为真(非零), 则求表达式2的值, 并把它作为整个表达式的值;如表达式1的值为假(零), 则求表达式3的值, 并把它作为整个表达式的值。  例如:  x=10;  y=x>9 ? 100:200;

72 2. 逗号运算符 逗号运算符“,”也称顺序求值运算符, 其运算优先级为15,也是最低的,结合方向是自左至右。 逗号运算符的左边总是不返回的,也就是说逗号右边表达式的值才是整个表达式的值。例如:  x=(y=3, y+1) 该表达式括号内是逗号表达式,由于结合方向是自左至右, 先将3赋给y, 然后计算表达式y+1,其值为4,逗号左边的值不返回,逗号右边的值才是整个表达式的值,所以表达式的值为4,最后将4赋给x。  由于逗号运算符的级别最低, 所以以整体先求值时一般均需加圆括号。

73 2.5.5 其它运算符 表 2.7 其它运算符

74 2.5.6 运算符的优先级和结合方向 表 2.8 C语言运算符的优先级和结合方向

75 表 2.8 C语言运算符的优先级和结合方向

76 2.6 表 达 式 2.6.1 C的各种表达式 1. 算术表达式 算术表达式的形式如下: 
<操作数><算术运算符><操作数> 算术表达式中运算对象(操作数)是数值, 也可以是字符(按其ASCII码值进行运算),运算结果(即表达式的值)是数值。如: a+b*c-d/e

77 2. 关系表达式 关系表达式的形式如下:  <操作数><关系运算符><操作数> 关系表达式中运算对象是数值,也可以是字符(取其ASCII码值), 其运算结果是逻辑量,即为“真”时取1,为“假”时取0。

78 3. 逻辑表达式 逻辑表达式的形式如下:  <操作数><逻辑运算符><操作数> 逻辑表达式的运算对象是逻辑量。在C语言中无逻辑量,因此规定将非零的值按“真”对待,零值按“假”对待。而运算结果为“真”时取1, 为“假”时取0。

79 4. 条件表达式 条件表达式的形式如下:  <表达式1> ? <表达式2>: <表达式3> 其中表达式1的值按逻辑值对待,非零为“真”,零值为“假”。 而当表达式1值为“真”(非零)时,条件表达式的值为表达式2的值; 而当表达式1的值为“假”(零)时,条件表达式的值为表达式3的值。如y=x ? a: b,若x=3则y=a,若x=0,则y=b。  表达式2或表达式3还可以是另一个条件表达式, 应注意它们是自右至左的结合方向。如a>b? a: c>d? c:d相当于a>b? a:(c>d? c:d), 当a=1, b=2, c=3, d=4时,此条件表达式的值等于4。

80 5. 逗号表达式 逗号表达式的形式如下:  表达式1,表达式2,…, 表达式n 逗号表达式按逗号间的顺序依次从左至右执行, 但整个逗号表达式的值为最后一个逗号右边表达式的值

81 6. 赋值表达式 赋值表达式是最常用的表达式, 形式如下:  <变量><赋值运算符><表达式> 赋值运算符即=,又称为赋值号。赋值号左边必须是变量、 数组元素等有存贮单元的元素,赋值号的右边可以是各类表达式, 也可以是另一个赋值表达式。因此a=b=c是合法的,即相当于a=(b=c),因为它是自右至左结合的,即c值先赋给b, b=c赋值表达式的值为b的值,然后再赋给a,整个表达式的值也为a的值。  赋值表达式的求值顺序是先计算赋值号右边表达式的值,再转换成表达式左边变量的类型,再进行赋值,此值也是赋值表达式的值。

82 2.6.2 表达式中的类型转换 转换的规则为:  (1) 转换的结果必定是3种基本类型:int, long或double型。 因此两个char型的数据运算,也要先转换成int型,运算结果也是int型;只要有一个数据是float型,都要先转换成double型,最后结果也是double型。

83 (2) 各类型级别由低到高的顺序为char, int, unsigned, long, unsigned long, float, double。除如(1)所述要进行char或short向int, float向double的转换外,其余类型的混合运算均按此顺序由低到高自动转换。另外,C语言规定,有符号类型数据与无符号类型数据进行混合运算,结果为无符号类型。例如,int型数据和unsigned类型数据的运算结果为unsigned型。

84 例 2.3 考虑图2.1中的类型转换。 图 2.1 类型转换示例

85 例 2.4 类型转换。  float x;  int i;  x=i= ; 则变量i的值为3, 而变量x的值为3.0而不是3, 也不是 。

86 (3) 可以使用强制类型转换。通过使用强制类型转换(type), 可以强迫表达式的值转换为某一特定类型。一般的形式是:
(类型) 表达式 其中类型(type)是C语言标准数据类型。 例如你想确保表达式x/2成为float型, 你可以写成如下形式:  (float)(x/2) 当然, 如x为整型时则会丢失信息。 如写成:  (float)x/2 则表达式的结果为double型。

87 例 2.5 整型数据相除。 程序:  main( ) { int i=100, j=40;  float f;  f=i/j;  printf(″f=%f\n″, f); } 运算结果为 f=

88 表 2.9 普通类型转换的结果

89 2.6.3 空格和圆括号 为了增加程序的可读性,在C程序的表达式中可以随意增加空格。 如以下两个表达式是等价的: 
x=10/y-(127/x) x = 10 / y - ( 127 / x ) 为了改变程序中表达式的求值顺序,可以加入圆括号。使用多余的圆括号并不会降低该表达式运行的速度,也不会引起错误。因此我们提倡使用圆括号来更清晰地表达运算次序, 也便于别人来读你的程序。

90 2.7 数据类型,运算符与表达式举例 例 2.6 书写下列算式的表达式。  (1) v=1/2at2 (2) d=a≤b≤c (3)
例 2.6 书写下列算式的表达式。  (1) v=1/2at2 (2) d=a≤b≤c (3) (4)

91 解  (1) v=0.5*a*t*t (2) d=(a<=b)&&(b<=c) (3) x1=(-b+sqrt(b*b-4*a*c))/(2*a) 表达式中的sqrt是求平方根函数,在程序中出现, 在程序首部加上:  #include <math.h>  (4) y=(sin(x)+cos(x))/tan(x) 表达式中的三个函数是三角函数, x的单位是弧度, 也属数学库函数,程序处理如(3)

92 例 2.7 已知各变量的值,写出类型说明语句并求表达式的值,再指出表达式最后的类型。 
已知:a=12.3, b=-8.2, i=5, j=4, c=′a′。  求: (1) a+b+i/j+c (2) i%j+c/i (3) a>b+c<=j (4) i<j&&j<c (5) i&j (6) i<<2|j>>1 (7) a>b? j:a

93 解 类型说明语句如下:  float a, b;  int i, j; char c;  (1) a+b+i/j+c = /4+′a′ = =102.1 (double型) (2) i%j+c/i =5%4+′a′/5 =1+97/5=1+19=20 (int型)

94 (3) a>b+c<=j =12.3>(-8.2)+′a′<=4 =12.3>( )<=4 =12.3>88.8<=4 =0<=4=1 (int型) (4) i<j&&j<c =5<4&&4<′a′ =0 (int型)(注: 4<′a′没有判断)

95 (5) i&j =5&4= &  = =4 (int型) (6) i<<2|j>>1 =5<<2|4>>1 = |  = =22 (int型) (7) a>b?j:a =12.3>(-8.2)?4: 12.3 =1?4:12.3 =4.0 (double型)


Download ppt "第二章 C的基本数据类型及运算 2.1 标识符 2.2 数据类型 2.3 常量 2.4 变量 2.5 运算符 2.6 表达式"

Similar presentations


Ads by Google