C/C++语言程序设计 第二章 数据类型和表达式 龚尚福,贾澎涛主编 《C/C++语言程序设计》 西安电子科技大学出版社
第2章 数据类型和表达式 2.1 词法构成 2.2 数据类型 2.3 常量与变量 2.4 指针类型 2.5 运算符和表达式 2.6 小结
第2章 数据类型和表达式 2.1 词法构成 字符集 标识符 关键字 注释符
字符集 C语言的字符集是ASCII字符集的一个子集,由字母,数字,标点符号和特殊字符构成。 (1)英文字母:a~z,A~Z (2)数字:0~9 (3)空白符:空格符,制表符,换行符等统称为空白符。 (4)特殊字符: ① 标点符号 ② 转义字符
字符集 表2.1 常用转义字符表 名称 符号 空字符(null) \0 换行(newline) \n 换页(formfeed) \f 回车(carriage return) \r 退格(backspace) \b 响铃(bell) \a 水平制表(horizontal tab) \t 垂直制表(vertical tab) \v 反斜线(backslash) \\ 问号(question mark) \? 单引号(single quotation marks) \' 双引号(double quotation marks) \” 1到3位8进制数所代表的字符 \ddd 1到2位16进制数所代表的字符 \xhh
标识符 C语言规定,标识符只能是字母(A~Z,a~z)、数字(0~9)、下划线( _ )组成的字符串,并且第一个字符必须是字母或下划线。 注意 (1)C语言中标识符严格区分大小写 (2)ANSI C标准规定标识符的长度可达31个字符 (3)标识符命名应“见名知义”; (4)变量名都要“先定义,后使用”。
关键字 ANSI C定义的关键字共32个,根据关键字的作用,可将其分为数据类型关键字、控制语句关键字、存储类型关键字和其它关键字四类 Microsoft C在ANSI C基础上扩展的关键字有(19个)
注释符 C语言的注释符是以 “/*”开头,并以 “*/”结尾,其间的内容为注释,一般出现在程序语句行之后,用来帮助阅读程序。
2.2数据类型 基本整型 长整型 短整型 整型 无符号整型 单精度型(float) 实型 基本类型 双精度型(double) 枚举类型(enum) 字符型(char) 数据类型 数组类型([ ]) 构造类型 结构体类型(struct) 共用体类型(union) 指针类型() 空类型(void)
整数类型 整型数就是通常使用的整数,分为带符号整数和无符号整数两大类。 1. 基本类型定义 类型说明符:int 例如,int a,b,c;
表2.2 Visual C++ 6.0 环境中整型数据属性表 整数类型 2. 整型数据的存储与取值范围 表2.2 Visual C++ 6.0 环境中整型数据属性表 数据类型 占用字节数 二进制位长度 值域 int 4 32 -2147483648~2147483647 short [int] 2 16 -32768~32767 long [int] [signed] int 同int [signed] short [int] 同short [signed] long [int] 同long unsigned [int] 0~65535 unsigned short [int] 同unsigned int unsigned long [int] 0~4294967295
整数类型 3. 整型数据的表示形式 十进制整数:254,-127,0都是正确的,而0291(不能有前导0)、23D (含有非十进制数码)都是非法的; 八进制整数:021,-017都是正确的,它们分别代表十进制整数17,-15,而256(无前缀0)、03A2(包含了非八进制数码)是非法的; 十六进制整数:0x12,-0x1F都是正确的,它们分别代表十进制整数18,31, 而5A (无前缀0x)、0x3H (含有非十六进制数码)是非法的。
实数类型 1. 基本类型定义 类型说明符:float(单精度型),double(双精度型),long double(长双精度型) 2. 实数存储与取值范围 在计算机中,实数是以浮点数形式存储的,所以通常将单精度实数称为浮点数。例如单精度实型数据在计算机中的存放形式见图2.1所示。其中,小数部分一般都采用规格化的数据形式。 图2.1单精度实型数据在计算机中的存放形式 1位 7位 23位 阶符 阶码 数符 尾数 指数部分 小数部分
实数类型 表2.3 MicroSoft C中实型数据属性表 数据类型 比特数(字节数) 有效数字 数的范围 float 32(4) 6~7 |-3.4E-38~3.4E+38| double 64(8) 15~16 |-1.7E-308~1.7E+308| long double 18~19
实数类型 3. 浮点数的表示形式 在C语言中,实数表示只采用十进制。它有二种形式: 十进制数形式和指数形式。 (1)十进制数形式。由整数、小数部分和小数点组成,整数和小数都是十进制形式。例如,0.123,-125.46,.78,80.0等都是合法形式。 (2)指数形式。由尾数、指数符号e或E和指数组成,尾数是小数点左边有且只有一位非零数字的实数。e或E前面必须有数字,e或E后面必须是整数。指数形式用于表示较大或者较小的实数。
字符类型 1. 基本类型定义 类型说明符:char 2. 字符型数据存储与取值范围 字符型数据的取值范围:ASCII码字符集中的可打印字符。字符数据存储占1个字节,存储时实际上存储的是对应字符的ASCII码值(即一个整数值)。
字符类型 3. 字符型数据的表示方法 字符型数据在计算机中存储的是字符的ASCII码值的二进制形式,一个字符的存储占用一个字节。因为ASCII码形式上就是0 到255之间的整数,因此C语言中字符型数据和整型数据可以通用。
字符类型 字符数据:指用单引号括起来的单个字符数据,如'A ', '%', ':','9'等。而'12'或'abc'是不合法的字符数据。 字符串数据:指用双引号括起来的单个或一串字符数据,如"good"、"0132"、"w1"、"a"等。注意"a"是字符串数据而不是字符数据。 为了便于C程序判断字符串是否结束,系统对每个字符串数据存储时都在末尾添加一个结束标志——即ASCII码值为0的空操作符'\0',它既不引起任何动作也不会显示输出,所以存储一个字符串的字节数应该是字符串的长度加1。
字符类型 例如"hello"在计算机中表示形式如图2.3所示: 'h' 'e' 'l' 'o' '\0' 104 101 108 111 图2.3 "hello"在计算机中的存储示意图
2.3常量与变量 2.3.1常量 常量 程序运行过程中不能被改变的量。 整数在计算机中是准确表示的,可以用十进制、八进制和十六进制数表示。当用八进制数表示时,第一位数字前面必须加0;当用十六进制数表示时,第一位数字前而必须加0x:无符号整数的末尾必须加字母u或U;长整数的末尾必须加字母I或L。 字符型常数是用单引号括住的单个字符。用转义字符表示不可显示字符。转义字符以“\”开头,后跟一个特定的字母或八进制数或十六进制数表示的ASCII代码值。
2.3常量与变量 符号常数是用标识符表示的常数,它具有变量的外表和常量的内涵。 用#define定义的符号常数没有类型和值的含义。在预编译时由编译系统将宏名用宏体替换。 define是编译预处理命令,不属于C语言关键字。 用const定义的符号常数既有值又有类型的含义。该定义是在编译阶段完成的。
2.3.2 变量 1. 变量的有关概念 在程序运行过程中,其值改变的数据,称为变量,变量用标识符表示,称为变量名。 变量必须“先定义后使用” 系统为变量分配存储单元,存储变量的值。 编写程序时通过变量名来存、取变量值。 变量名 例如: 有变量x 它的值是98 x 98 变量值 为变量分配的存储单元
2. 变量定义 变量定义的一般格式: 例如:int i, j; long k, m; float x,y; char ch1,ch2; 【类型修饰符】数据类型 变量表; 必须使用合法的标识符作变量名 不能使用关键字为变量命名 分号是语句的组成部分 C语言的变量名和它的类型无关; 在函数或复合语句中必须把要定义的变量全部定义,即不允许在后面的执行语句中插入变量的定义。 解释: 1. 在此统一说一下变量说明的格式。 强调先说明后使用的规则。 2. 在解释变量初始化时强调变量必须先赋值后引用。 23
5. 变量的初始化 允许在说明变量的时候对变量赋初值。 例如:int a=5,b=10+2; double x=23.568,y ; char ch1='a',ch2=66,ch3='\142'; 表示定义变量并对变量存储单元赋值。 错误的初始化: int a=3+b,b=5; float m=n=23.16;
5. 变量的初始化 (1)注意变量在赋值或运算时,其值要在该数据类型的值域内,否则会产生数据溢出。 (2)由于实型变量是由有限的存储单元组成的,因此能提供的有效数字总是有限的,在有效位以外的数字将被舍去,由此可能会产生一些误差。 (3)字符型数据与整型数据可通用,增加了程序设计的自由度,例如对字符作多种转换就比较方便。但也需注意,字符型数据与整型数据的通用是有条件的,即在0~255的范围之内才可以通用。
5. 变量的初始化 【例2.1】 整型数据的溢出。 #include "stdio.h" void main() { short int a,b; a=32767; b=a+1; printf("a:%d,b:%d" , a , b); } 运行结果为: a:32767, b:-32768
5. 变量的初始化 #include "stdio.h" void main() { float a,b,c,d; 【例2.2】 实型数据的舍入误差。 #include "stdio.h" void main() { float a,b,c,d; a=12345.6789e3; b=12345.6784e3; c=a+10;/*理论值应是12345688.900000*/ d=b+10;/*理论值应是12345688.400000*/ printf("c=%f\n", c); /*实型变量只能保证的有效数字是7位有效数字,运行结果是理论结果四舍五入得到的*/ printf("d=%f\n", d); } 运行结果 c=12345689.000000 d=12345688.000000
5. 变量的初始化 【例2.3】计算字符'B'与整型数据20的和。 #include "stdio.h" void main() { char a; /* 说明a为字符型变量 */ int b; /* 说明b为整型变量 */ a='B'; /* 为a赋字符常量'B' */ b=a+20; /* 计算66+20并赋值给字符变量b */ printf("%c,%d,%c,%d\n",a,a,b,b); /* 分别以字符型和整型两种格式输出a、b */ } 程序运行的输出结果如下: B,66,V,86
2.4 指针和指针变量 2.4.1 指针和指针变量的概念 main() {float x; int y; … } 2000 2001 变量的两个物理意义 2000 2001 2002 2003 2004 2005 … x y main() {float x; int y; … } 变量的内容 变量的地址
2.4.1指针和指针变量的概念 利用变量名存取数据的方式称为“直接存取”方式。 void main() {int a,b,c; a=5; c=a +b; … } 2000 2001 2002 2003 2004 2005 5 直接将整数 5 存入变量 a a b c 3 直接将整数 3 存入变量 b 8 直接将变量 a、b 的值取出,相加后存入变量 c 利用变量名存取数据的方式称为“直接存取”方式。
2.4.1指针和指针变量的概念 p=&c C 语言还提供了对内存单元的“间接存取”方式 void main() 2000 2001 2002 2003 2004 2005 2006 2007 a b c 5 void main() {int a=5,b=3,c,*p; p = &c; *p = a + b; … } 3 8 ●变量的地址称为变量的指针 ●存放地址的变量称为指针变量 2004 a和b相加的结果(*p=a+b)存放到变量p所指向的内存单元中去。此时c称为指针变量p的目标变量。 P 2004 c p=&c
2.4.2指针变量的定义 void main() void main() {int a,*p; { int a,*p=&a; float x,*q; p = &a; q = &x; … } 指针变量定义的形式 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 a p x q 指针变量初始化 void main() { int a,*p=&a; float x,*q=&x; … } 2000 2004
2.4.2指针变量的定义 指针变量的引用 关于对指针变量的引用,通过上述已经出现的两个相关的运算符进行说明。 (1)*:称为指针运算符或称为“间接访问内存地址”运算符;在定义时,通过它标明某个变量被定义为指针变量,而在使用时,*p则表示p所指向变量的内容。 (2)&:称为取地址运算符,通过它获得目标变量所在存储单元的地址。
2.5 运算符和表达式 主要内容: 算术运算符和算术表达式 赋值运算符和赋值表达式 关系运算符和关系表达式 逻辑运算符和逻辑表达式 位运算符和位运算表达式 条件运算符和条件表达式 逗号运算符和逗号表达式 其他运算符及其运算
运算符的有关概念 作用: 对运算对象完成规定的操作运算 类型: 按运算对象分: 单目、双目、三目 按功能分: 算术、赋值、关系、逻辑 条件、逗号、位、其他
运算符的优先级和结合性 优先级 结合性 指各种运算符号的运算优先顺序 例如:算术运算优先于关系运算 算术运算中先 * / 后 + - 指运算符号和运算对象的结合方向 分为:从左向右(左结合)和从右向左(右结合) 例如:算术运算符为左结合 a-b+4 赋值运算符为右结合 a= b = 5
运算符的优先级和结合性 表2.6 运算符优先级和结合性 优先级 运算符 名称 操作数个数 结合规则 1 ( ) [ ] -> ﹒ ( ) [ ] -> ﹒ 圆括号运算符 数组下标运算符 指向结构指针成员运算符 取结构成员运算符 (从左至右) 2 ! ~ ++ -- - (类型) * & sizeof 逻辑非运算符 按位取反运算符 自增运算符 自减运算符 负号运算符 强制类型转换运算符 取地址的内容(指针运算) 取地址运算符 求字节数运算符 (单目运算符) <- (从右至左)
运算符的优先级和结合性 优先级 运算符 名称 操作数个数 结合规则 3 * / % 乘法运算符 除法运算符 求余运算符 2 (双目运算符) -> 4 + - 加法运算符 减法运算符 5 << >> 左移运算符 右移运算符 6 < <= > >= 小于运算符 小于等于运算符 大于运算符 大于等于运算符 7 == != 等于运算符 不等于运算符
运算符的优先级和结合性 优先级 运算符 名称 操作数个数 结合规则 8 & 按位“与”运算符 2 (双目运算符) -> 9 ^ 按位“异或”运算符 10 | 按位“或”运算符 11 && 逻辑与运算符 12 || 逻辑或运算符 13 ?: 条件运算符 3 (三目运算符) <-
运算符的优先级和结合性 优先级 运算符 名称 操作数个数 结合规则 14 = += -= *= /= %= = += -= *= /= %= >>= <<= &= ^= |= 赋值运算符 2 (双目运算符) <- 15 , 逗号运算符(顺序求值运算符) ->
表达式的有关概念 什么是表达式 表达式由运算符和操作数组成,操作数是运算符的操作对象,可以是常量、变量、函数和表达式。 表达式的书写 C语言的表达式采用线性形式书写。 数学表达式 应该写成 1/6-i+j*j*j*j*j*j。 C语言的表达式只能使用C语言中合法的运算符和操作数 2πr应该写成2*3.14159*r
例如: 表达式: 150+'b'*2-12.456 b=(++a)-2 a /= a *= (a = 2) f=a>b>c max=a>b ? a : b a=3,a+=3,a*a 1/(float)a+6
算术运算 算术运算符的优先级 ( ) + - ++ -- * / % + - 同级 同级 同级 单目 双目 高 低
算术运算 没有乘方运算符,要计算a3要写作 a*a*a 的连乘,或用标准库函数 pow(a, 3) “/”的运算对象可为各种类型数据,但是当进行两个整型数据相除时,运算结果也是整型数据 “%”要求运算对象必须是整型数据,功能是求两数相除的余数,余数的符号与被除数的符号相同。
自增自减运算 ++ --是单目运算符 有前缀和后缀两种形式 前缀形式: 先自增(自减)再引用; 后缀形式: 先引用再自增(自减); 功能: 前缀形式 ++ a 等价于 a = a + 1 -- a 等价于 a = a – 1 后缀形式 a ++ 等价于 a = a + 1 a -- 等价于 a = a – 1
例如: 当 a=5 时 ⑴ ++a 表达式的值为 6,且 a=6 ⑵ a++ 表达式的值为5 ,且 a=6 ⑶ b=++a 等价于 a=a+1; b=a 表达式的值为6,且 a=6, b=6 ⑷ b=a++ 等价于 b=a; a=a+1 表达式的值为5,且 a=6, b=5
说明: 自增、自减运算符只能用于整型变量,而不能用于常量或表达式。 例如: 5++、(a+2)++ 不合法。 具有右结合性,结合方向为从右到左。 例如: –a++ 等价于 -(a++) C语言的表达式中“++”,“--”运算符,如果使用不当,很容易导致错误。 例如:设i=3,表达式k=(++i)+(++i)+(++i)” 不同的C编译系统结合方式不一样,所以不同的编译系统中,针对上述表达式得出的答案并不一定同编程者的原意相同。
说明: 【例2.6】自增自减运算的应用。 #include “stdio.h” void main() { int i,j; i=j=5; printf (“i++=%d, j--=%d\n”, i++, j--); printf (“++i=%d, --j=%d\n”, ++i, --j); printf (“i=%d, j=%d\n”, i, j); } 运行结果: i++=5, j--=5 ++i=7, --j=3 i++=7, j--=3 ++i=9, --j=1 i=9, j=1
关系运算 > >= < <= == != 较高 较低 用关系运算符将运算对象连接成的式子 例如: 关系运算符 (左结合) > >= < <= == != 较高 较低 关系表达式 用关系运算符将运算对象连接成的式子 例如: 12< 'C'+1 (字符型数据比较ASCII值) a==b>=c 等价于 a == ( b>=c ) 与 (a==b)>=c 不等价 关系运算符优先于赋值,低于算术
说明: 关系运算的结果应该是逻辑值。C语言用数值用 1 表示逻辑真, 0 表示逻辑假 例如: 7>5 的值是 1,5>7 的值是 0 'a'>'b'的值是 0, 'a'<'b' 的值是1 即关系表达式的值:0 或1 实型数可进行大于或小于比较,但通常不进行 == 或 != 的关系运算
逻辑运算符 逻辑运算符 && || ! 逻辑运算符的运算规则 运算对象 逻辑运算结果 a b a&&b a || b !a 非0 1
逻辑表达式 逻辑表达式 用逻辑运算符将运算对象连接成的式子 例如:0&&'b' a &&b || c&&d a || b-5 || c/4 !x+y >= z 逻辑运算符的优先级 和结合性: !是单目运算符,右结合,高于算术 && 和 || 是双目运算符,左结合,高于赋值运算符,低于关系运算符
逻辑运算规则 从左到右依次进行逻辑计算 运算对象为非0表示逻辑真 运算对象为 0 表示逻辑假 逻辑运算的结果为 0 或 1 例如设:a=15,b=0,c=-2 a && b && c 结果为0 a || b || c 结果为1 (a+c) || b && c 结果为1
逻辑运算规则(续) 运算按照从左至右的顺序进行,一旦能够确定逻辑表达式的值,就立即结束运算 ——逻辑运算的短路性质 例如设:a=1,b=0,c=-2 a && b && c 为 0,运算终止,表达式值为 0 (a++) || ++ b&& --c 为非0,运算终止,表达式值为 1 且a为2,b为0,c为-2 (b,c保持原值)
关系与逻辑运算符的应用 表示数学公式a>b>c 判断a, b, c三条线段能否组成一个三角形 a>b && b>c a+b>c && a+c>b && b+c>a a>=0 || b>=0 !(a<0 && b<0) (a<0&&b>=0)||(a>=0&&b<0)||(a>=0&&b>=0)
条件表达式运算 条件运算符:? : 条件表达式的一般形式 表达式1 ? 表达式2 : 表达式3 例如:m<n ? x : a+3 a++>=10 && b-->20 ? a : b x=3+a>5 ? 100 : 200 C语言中唯一的三目运算符,要正确区分用 ?和 :分隔的表达式 涉及条件运算符的优先级与结合性
条件运算符优先级 条件运算符优先级高于赋值、逗号运算符,低于其他运算符 例如: ⑴ m<n ? x : a+3 ⑵ a++>=10 && b-->20 ? a : b ⑶ x=3+a>5 ? 100 : 200 等价于:(m<n) ?(x) :(a+3) 等价于:(a++>=10 && b-->20) ? a : b 等价于:x= (( 3+a>5 ) ? 100 : 200 )
条件运算符的结合性 条件运算符具有右结合性 当一个表达式中出现多个条件运算符时,应该将位于最右边的问号与离它最近的冒号配对,并按这一原则正确区分各条件运算符的运算对象。 例如:w<x ? x+w : x<y ? x : y 与 w<x ? x+w : ( x<y ? x : y) 等价 与 (w<x ? x+w : x<y) ? x : y 不等价
条件运算符的结合性 【例2.7 】条件表达式的应用——判断整数的正负 #include "stdio.h" void main() { int x; scanf("%d", &x); x>0?printf("%s","Positive"):printf("%s","Negative"); }
逗号表达式运算 逗号表达式的一般形式 表达式1,表达式2,……,表达式n 逗号表达式的值 例如:⑴ a=5, a++, a* 3 表达式值为 18,且a=6 ⑵ t=1, t+5, t++ 表达式值为 1,且t=2 ⑶ x=(a=3*5, a*4 ) 赋值表达式的值为60,且x=60, a=15
赋值运算 赋值运算符(右结合) = += -= *= /= %= &= |= ^= >>= <<= 赋值表达式 = += -= *= /= %= &= |= ^= >>= <<= 赋值表达式 将表达式的值存入变量对应的内存单元中 m=12 b=(++a)-2 m%=3+n 等价于 m=m%(3+n) x *= (x = 5)
说明: 赋值号左边必须是变量,右边可以是C语言任意合法的表达式 例如:n= t +2<s 合法 a+ b = 15 不合法 赋值运算符仅优先于“,” ,且具有右结合性 例如: a= b= b*c>10 等价于:a= (b=( (b*c)>10) ) 赋值号与数学中的等号含义不同 例如:数学中 a=b 等价于 b=a C语言中 a=b 不等价于 b=a
说明: 【例2.8】 赋值运算应用实例。 #include "stdio.h" void main() 运行结果为: { int i, j; float x, y; i=j=1; x=y=1.1f; printf ("i=%d, j=%d\n", i, j); x=i+j; y+=1;/*等价于y=y+1*/ printf ("x=%4.2f,y=%4.2f\n", x, y); i=i+++j; x=2*x+y; printf (“i=%d, x=%4.2f\n”, i, x); } 运行结果为: i=1, j=1 x=2.00, y=2.10 i=3, x=6.10
位运算符 ~ & ^ | << >> 位逻辑运算符 移位运算符 单目 ~ & ^ | << >> 位逻辑运算符 移位运算符 低于单目、算术和关系运算符,高于其他运算符 低于单目、算术运算符,高于其他运算符 位运算符的运算对象只能是整型数据或字符型数据,不能是实型数据 运算对象一律按二进制补码参加运算,并按位进行运算 位运算的结果是一个整型数据
位运算符 ~运算常用于产生一些特殊的数。 例如: ~运算还常用于加密子程序。 初始字节内容 00000101 取反后 11111010 (1)位逻辑运算 按位取反运算 按位取反运算符:~ 按位取反运算用来对一个二进制数按位求反,即“1”变为“0”,“0”变为“1 ~运算常用于产生一些特殊的数。 ~运算还常用于加密子程序。 例如: 初始字节内容 00000101 取反后 11111010
位运算符 按位与运算 按位与运算符:& 按位与运算的规则是当两个操作数的对应位都是1时,则该位的运算结果为1,否则为“0“。 例如:0x29&0x37的运算 0x29: 00101001 0x37: 00110111 与运算结果为:00100001,即0x21。
位运算符 按位与运算主要用途是清零、指定取操作数的某些位或保留操作数的某些位。 例如: a&0运算后,将使数a清0。 a&0xF0运算后,保留数a的高4位为原值,使低4位清0。 a&0x0F运算后,保留数a的低4位为原值,使高4位清0。
位运算符 按位或运算 按位或运算符:| 按位或运算的规则是当两个操作数的对应位都是0时,则该位的运算结果为0,否则为1。 例如:0x29|0x37的运算 0x29: 00101001 0x37: 00110111 按位或结果:00111111,即等于0x3f。
位运算符 利用或运算的功能可以将操作数的部分位或所有位置为1。 例如: a|0x0F运算后,使操作数a的低4位全置1,其余位保留原值。 a|0xFF运算后,使操作数a的每一位全置1。
位运算符 按位异或运算 按位异或运算符:^ 按位异或运算的规则是当两个操作数的对应位相同时,则该位的运算结果为0,否则为1。 例如:0x29^0x37的运算 0x29: 00101001 0x37: 00110111 按位异或结果:00011110,即等于0x1e
位运算符 利用^运算的功能可以将数的特定位翻转,保留原值,不用中间变量就可以交换两个变量的值。 例如: a^0x0F运算后,将操作数a的低4位翻转,高4位不变。 a^0x00运算后,将保留操作数a的原值。 a=a^b;b=b^a;a=a^b;运算后,不用中间变量交换a、b的值,就可以实现操作数a和b的交换。
位运算符 移位运算 向左移位运算 左移位运算符:<< 左移位运算的左操作数是要进行移位的整数,右操作数是要移的位数。左移位运算的规则是将左操作数的高位左移后溢出并舍弃,空出的右边低位补0。 例如:15<<2运算 15: 00001111 左移2位的结果为:00111100,等于60。 使用左移位运算可以实现快速乘2运算。
位运算符 右移位运算 右移位运算符:>> 右移位运算的左操作数是要进行移位的整数,右操作数是要移的位数。右移位运算规则是低位右移后被舍弃,空出的左边高位,对无符号数补入0;对带符号数,正数时空出的左边高位补入0,负数时空出的左边高位补入其符号位的值(算术右移)。 例如:15>>2的运算, 15: 00001111 右移2位的结果:00000011 结果为3; -15>>2的运算 -15:11110001 右移2位的结果为:11111100,结果为-4。 使用右移位运算可以实现快速除2运算。
位运算符 【例2.9】 取一个正整数a(用二进制数表示)从右端开始的4~7位(最低位从0开始)。 #include "stdio.h" void main() { unsigned int a,b,c,d; scanf("%o",&a); /* 八进制形式输入 */ b=a>>4; /* a右移四位 */ c=~(~0<<4); /* 得到一个4位全为1,其余位为0的数 */ d=b&c; /* 取b的0~3位,即得到a的4~7位 */ printf(“a=%o, a(4~7)=%o”,a,d); } 输入数据: 331 运行结果为: a=331,a(4~7)=15
取地址运算符 & 为单目运算符 运算对象只能是变量 运算结果是变量的存储地址 例如有定义: int a , student; char ch; 可以对变量a、ch、student 进行&运算: &a &ch &student
长度运算符 sizeof 为单目运算符 运算对象只能是变量名或数据类型标识符 运算结果为该变量或该数据类型的长度 TC环境中输出结果: void main( ) { int a=5; double x; printf("%d %d ",sizeof(int),sizeof(a)); printf("%d %d ",sizeof(double),sizeof(x)); printf("%d %d\n",sizeof(float),sizeof(char)); } TC环境中输出结果: 2 2 8 8 4 1
运算中数据类型的转换 1.数据类型的自动转换 char, short double long float unsigned int 高精度 转换原则:自动将精度低、表示范围小的运算对象类型向精度高、表示范围大的运算对象类型转换 char, short double long float unsigned int 高精度 低精度 例如有定义: int a; char ch; 表达式: a-ch*2+35L a-ch*2+ 35.
2.数据类型的强制转换 强制转换的一般形式 例如: (int)( 'b'+3*x)%3 (类型名) 表达式 1/(float)a+6 注意: (float) 22/5 与 (float) (22/5) 不同 错误的类型转换: (int) b=a+5 b= int (3*a)
3. 赋值表达式中的类型转换 将实型数据(包括单、双精度)赋给整型变量时,舍弃实数的小数部分。 将整型数据赋给单、双精度变量时,数值不变,但以浮点数形式存储到变量中。 将一个double型数据赋给float变量时,截取其前面7位有效数字,存放到float变量的存储单元(32位)中。但应注意数值范围不能溢出。 字符型数据赋给整型变量时,由于字符只占1个字节,而整型变量为2个字节(TC环境下),因此将字符数据(8位)放到整型变量低8位中。
3. 赋值表达式中的类型转换 在某些编译环境下,将带符号的整型数据(int 型)赋给long型变量时,要进行符号扩展,将整型数的16位送到long型低16位中,如果int型数据为正值(符号位为“0”),则long型变量的高16位补“0”;如果int型变量为负值(符号位为“1”),则long型变量的高16位补“1”,以保持数值不改变。反之,若将一个long型数据赋给一个int型变量,只将long型数据中低16位原封不动地送到整型变量(即截断)。
3. 赋值表达式中的类型转换 将unsigned int型数据赋给long int型变量时,不存在符号扩展问题,只需将高位补“0”即可。 将非unsigned型数据赋给长度相同的unsigned型变量,也是原样照赋(连原有的符号位也作为数值一起传送)。
3. 赋值表达式中的类型转换 【例2.10】 赋值表达式中的类型转换。 void main() { int i=43; float a=55.5,a1; double b=123456789.123456789; char c='B'; printf("i=%d,a=%f,b=%f,c=%c\n",i,a,b,c); /* 输出i,a,b,c的初始值 */ a1=i; /* int型变量i的值赋值给float型变量a1*/ i=a; /*float型变量a的值赋给int型变量i,会舍去小数部分*/
3. 赋值表达式中的类型转换 a=b; /*double型变量b的值赋值给float型变量a,有精度损失*/ c= i; /*int型变量i的值赋值给char变量c,会截取int型低8位*/ printf("i=%d,a=%f,a1=%f,c=%c\n",i,a,a1,c); /*输出i,a,a1,c赋值以后的值 */ } 运行该程序的输出结果如下: i=43,a=55.500000,b=123456789.123457,c=B i=55,a=123456792.000000,a1=43.000000,c=7
小结 1.C的数据类型(基本类型,构造类型,指针类型,空类型)及其定义方法。 2.C运算符的种类、运算优先级和结合性。 4.不同类型数据间的转换与运算。