460 likes | 635 Views
第二章 数据类型、运算符、表达式. 数据类型 常量与变量 整型、实型、字符型 不同类型数据间的转换 运算符和表达式. 整 型. 基本类型. 单精度型 float. 实型. 双精度型 double. 字符类型 char. 枚举类型 enum. C 数 据 类 型. 短整型 short. 数组. 整型 int. 构造类型. 结构体 struct. 长整型 long. 共用体 union. 指针类型. 空类型 void. 2.1 数据类型. <. >. 2.2 常量与变量 常量和符号常量
E N D
第二章 数据类型、运算符、表达式 数据类型 常量与变量 整型、实型、字符型 不同类型数据间的转换 运算符和表达式
整 型 基本类型 单精度型float 实型 双精度型double 字符类型char 枚举类型enum C 数 据 类 型 短整型short 数组 整型int 构造类型 结构体struct 长整型long 共用体union 指针类型 空类型void • 2.1数据类型 < >
2.2常量与变量 常量和符号常量 常量:在程序运行过程中,其值不能改变的量 如;12,0,-3,4.6,-1.23,‘a’,’c’ 符号常量:用一个标识符代表一个常量 例2.1 符号常量的使用 #define PRICE 30 main() { int num,total; num=10; total=num* PRICE; printf(“total=%d”,total); } 运行结果: total=300 < >
符号常量的好处 含义清楚 如 PRICE 代表价格 能做到一改全改 如 #define PRICE 35 程序中所有以PRICE代表的价格自动改为35 变量名 a 3 变量值 存储单元 • 变量 • 在程序运行过程中,其值可以改变的量 • 变量有一个名字 • 变量在内存中占一定的存储单元 < >
标识符 定义:用来标识变量、常量、函数等的有效字符序列 组成: 只能由字母、数字、下划线组成,且第一个字母必须是字母或下划线 大小写敏感 命名原则: 见名知意 变量名尽量用小写,符号常量用大写 长度尽量不要超过8个字符 尽量不使用下划线开头 不能用关键字作标识符 避免使用容易认错的字符 • 例: 0 o O • 1 l I • Z z 2 • 例:判断下列标识符号合法性 • sum Sum M.D.John day Date 3days • student_name #33 lotus_1_2_3 • char a>b _above $123 M.D.John 3days #33 char a>b $123 < >
变量的使用应“先定义,后使用” • 未被事先定义的不作为变量名 例:如果在定义部分写了 int student ; 而在执行语句中错写成stadent. 如:stadent =30; 则输出错误“变量stadent未定义” • 编译时根据变量的类型为其分配相应的存储单元 如 int为两个字节 float为四个字节 • 编译时根据变量的类型检查运算是否合法 如 % 运算只能在整型数据之间进行 如果a,b为两个实型变量,则a%b是错误的
2.3整型数据 整型常量的表示方法 十进制整数 如;123,-456,0 八进制整数 以0开头的数 如:0123即(123)8 其值为1*82+2*81+3*80=83 十六进制整数 以0x开头的数 如:0x123即(123)16 其值为1*162+2*161+3*160=291 注 要注意各种进制数字的组成 < >
各种进制之间的转换 • 二进制、八进制、十六进制转换成十进制 • 方法:按权相加 < >
例 把十进制数159转换成八进制数 余 7 余 3 余 2 例 把十进制数59转换成二进制数 0 2 8 59 159 1 余 2 2 2 8 2 8 2 7 19 3 14 29 1 2 (159)10=(237)8 余 1 例 把十进制数459转换成十六进制数 余 0 2 3 7 1 C B 余 1 459 16 余11 余 1 余12 16 28 余 0 1 16 1 余 1 1 1 1 0 1 1 0 (59)10=(111011)2 (459)10=(1CB)16 • 各种进制之间的转换(整数) • 二进制、八进制、十六进制转换成十进制 • 方法:按权相加 • 十进制转换成二进制、八进制、十六进制 • 方法:连续除以基,从低到高记录余数,直至商为0
二进制与八进制之间的转换 • 二进制转换成八进制:从右向左,每3位一组(不足3位左补0),转换成八进制 • 八进制转换成二进制:用3位二进制数代替每一位八进制数 000 ~ 0 001 ~ 1 010 ~ 2 011 ~ 3 100 ~ 4 101 ~ 5 110 ~ 6 111 ~ 7 例 (1101001)2=(001,101,001)2=(151)8 例 (246)8=(010,100,110)2=(10100110)2 < >
二进制与十六进制之间的转换 • 二进制转换成十六进制:从右向左,每4位一组(不足4位左补0),转换成十六进制 • 十六进制转换成二进制:用4位二进制数代替每一位十六进制数 0000 ~ 0 0001 ~ 1 0010 ~ 2 0011 ~ 3 0100 ~ 4 0101 ~ 5 0110 ~ 6 0111 ~ 7 1000 ~ 8 1001 ~ 9 1010 ~ A 1011 ~ B 1100 ~ C 1101 ~ D 1110 ~ E 1111 ~ F 例 (11010101111101)2=(0011,0101,0111,1101)2=(357D)16 例 (4B9E)16=(0100,1011,1001,1110)2=(100101110011110)2 < >
0 1 2 3 4 5 7 6 7 6 5 4 3 2 1 0 7 6 8 5 9 4 10 3 ……... 2 1 • 字节和位 • 内存以字节为单元组成 • 每个字节有一个地址 • 一个字节一般由8个二进制位组成 • 每个二进位的值是0或1 < >
整型变量 整型数据在内存中的存放 在内存中以二进制形式存放 一个整型变量在内存中占两个字节 如:int i ;i=10;数据在内存中的实际存放情况 补码 正数的补码和其原码形式相同 负数的补码 取-10的绝对值 按位取反 加1 0 1 0 1 0 1 0 1 1 1 0 0 0 1 0 1 0 1 0 1 0 0 0 0 1 0 0 0 0 1 1 1 1 1 1 1 0 1 1 1 1 1 0 1 0 0 1 1 1 0 0 0 0 1 0 0 1 0 0 1 1 0 0 1 < >
符号位 1 0 =32767 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 =65535 数据的第一位 • 整型变量的分类 • 有符号基本整型 [signed] int • 无符号基本整型 unsigned int • 有符号短整型 [signed] short [int] • 无符号短整型 unsigned short [int] • 有符号长整型 [signed] long [int] • 无符号长整型 unsigned long [int] 有符号整型变量 无符号整型变量
整型变量的定义 int a,b; unsigned short c,d; long e,f 例2.2 整型变量的定义与使用 main() { int a,b,c,d; unsigned u; a=12;b=-24;u=10; c=a+u;d=b+u; printf(“a+u=%d,b+u=%d\n”,c,d); } 运行结果: a+u=22,b+u=-14 < >
整型数据的溢出 32767 a: 0 1 0 0 1 1 0 1 0 1 0 0 1 1 0 1 0 0 1 1 0 1 1 1 1 0 0 0 0 1 -32768 b: 0 1 例2.3 整型数据的溢出 main() { int a,b; a=32767; b=a+1; printf(“%d,%d\n”,a,b); } 运行结果: 32767,-32768 < >
12 1 11 2 10 9 3 8 4 5 7 6 • 整型常量的类型 • 其值在-32768~+32767范围内的整数认为它是int 型 • 其值超出上述范围,在-2147483648~+2147483647范 围内,则认为是长整型 • 一个整型常量后加一个字母u,认为是unsigned int 型 如12345u。如果是-12345u,则先将-12345转换成补码 53191,然后按无符号数存储。 • 一个整型常量后面加一个字母l或L,认为是long int 型
思考题 请写出下列程序的运行结果 main() { long int a; a=32767+1; printf(“a=%ld\n”,a); } main() { long int a; a=32768; printf(“a=%ld\n”,a); } < >
2.4实型数据 实型常量的表示方法 十进制小数形式 由数字和小数点组成(必须有小数点) 如;.123、123.、123.0、0.0 指数形式 如:123e3或123E3 都代表123*103 字母e之前必须有数字,e后面的指数必须为整数 规范化的指数表示形式 一个实数可以有多种指数表示形式 如123.456可表示为123.456e0、12.3456e1、 1.23456e2、0.123456e3等 字母e之前的小数部分中,小数点左边有且只能有一位 非零的数字 < >
实型变量 实型数据在内存中的存放 实型变量的分类 .314159 1 + 数符 指数 小数部分 < >
实型数据的舍入误差 例2.4 实型数据的舍入误差 main() { float a,b; /*double*/ a=123456.789e5; b=a+20; printf(“%f\n”,b); } 运行结果: 12345678848.000000 • 实型常量的类型 系统将实型常量作为双精度来处理 可在数的后面加字母f或F,按单精度处理 < >
2.5 字符常量 • 定义:用单引号括起来的单个普通字符或转义字符. 如 ‘a’ ‘A’ ‘?’ ‘\n’ ‘\101’ • 转义字符:反斜线后面跟一个字符或一个代码值表示 例 转义字符举例 main() { printf("\101 \x42 C\n"); printf("I say:\"How are you?\"\n"); printf("\\C Program\\\n"); printf("Turbo \'C\'"); } 例: ‘A’-------’\101’-------’\x41’--------65 如 ‘\101’ -----------‘A’ ‘\012’ -----------’\n’ ‘\376’ -----------’’ ‘\x61’ -----------’a’ ‘\60’ -----------’0’ ‘\483’ ----------() 运行结果:(屏幕显示) A B C Isay:”How are you?” \C Program\ Turbo ‘C’ 例 main() { printf(“Y\b=\n”); } 运行结果: 屏幕显示:= 打印机输出:¥
运行结果: 屏幕显示:f gde h j k 打印机输出:fab c gde h jik 例2.5转义字符的使用 main() { printf(“ ab c\t de\rf\tg\n"); printf(“h\ti\b\bj k\n"); } • 字符变量 • 定义形式 char c1,c2; • 赋值 c1=‘a’;c2=‘b’;
‘a’在内存中的存储 ‘b’在内存中的存储 01100001 01100010 字符 ASCII码 输出 c1=‘a’;c2=‘b’ 输出 ASCII码 字符数据和整型数据存储形式相似,可以互相转换 • 字符数据在内存中的存储 • 一个字符在内存中占一个字节 • 字符数据在内存中以ASCII码存储 例2.6向字符变量赋以整数 main() { char c1,c2; c1=97;c2=98; printf(”%c %c\n”,c1,c2); printf(”%d %d\n”,c1,c2); } 一个字符型数据既可以以字符形式输出,也可以以整数形式输出 运行结果: a b 97 98
注 例2.7大小写字母的转换 main() { char c1,c2; c1='a';c2='b'; c1=c1-32; c2=c2-32; printf("%c %c\n",c1,c2); } 运行结果: A B 字符数据与整型数据可以互相赋值 int i;char c; i=‘a’;c=97; 字符变量中的最高位为符号位
h e l l o \0 例 字符串“hello”在内存中 例 ‘a’ “a” a a \0 例: char ch; ch=‘A’; • 字符串常量 • 定义:用双引号(“”)括起来的字符序列 • 存储:每个字符串尾自动加一个 ‘\0’ 作为字符串结束标志 如 “how do you do”,“china”,”a” • 字符常量与字符串常量不同 例: char ch; ch=“A”; <
类型 符号 关键字 数的表示范围 所占位数 (signed)int 16 -32768~32767 16 (signed)short -32768~32767 32 (signed)long -2147483648~2147483647 unsignedint 16 0~65535 unsignedshort 16 0~65535 unsignedlong 32 0~4294967295 32 float 有 10-37~1038 64 有 double 10-307~10308 8 有 char -128~127 无 8 0~255 unsigned char • ANSI标准定义的数据类型 有 整型 无 实型 字符型 < >
2.6 变量赋初值 定义变量的同时使变量初始化 如:int a=3;float f=3.56;char c=‘a’; 也可部分赋初值 如:int a,b,c=3; 对几个变量赋初值,可写成 int a=3,b=3,c=3; 不能写成 int a=b=c=3; int a; a=3; int a,b,c; c=5; int a=3; int a,b,c=5; < >
double float 说明: 高 必定的转换 long 运算对象类型不同时转换 只表示转换方向 unsigned 例 int i; float f; double d; long e; int char,short 低 10+‘a’ +i*f - d/e ch/i + f*d - (f+i) 例 char ch; int i; float f; double d; int double double double double int int double double double double double int double double double • 2.7各类数值型数据间的混合运算 < >
2.8算术运算符和算术表达式 算术运算符:+ - * / % ++ -- 关系运算符:< <= = = > >= != 逻辑运算符:! && || 位运算符 :<< >> ~ | ^ & 赋值运算符:= 及其扩展赋值运算符 条件运算符:?: 逗号运算符:, 指针运算符:* & 求字节数 :sizeof 强制类型转换:(类型) 分量运算符:. -> 下标运算符:[] 其它 :( ) - C 运 算 符 < >
算术运算符和表达式 基本算术运算符: + - * / % 说明: 两整数相除,结果为整数 采取“向零取整”的方法 %要求两侧均为整型数据 例 5%2 = 1 -5%2 = -1 1%10 =1 5%1 =0 5.5%2 () 例 5%2 = -5%2 = 1%10 = 5%1 = 5.5%2 例 5/2 = 5/2.0 = 例 5/2 = 2 5/2.0 =2.5 < >
算术表达式和运算符的优先级与结合性 C算术表达式:用算术运算符和括号将运算对象连接起来的、符合C语法规则的式子 结合方向为“自左至右” 例 a*b/c-1.5+’a’ ab*c/1.5-’a’+ 例2.8强制类型转换 main() { float x; int I; x=3.6; i=(int) x; printf(”x=%f,i= %d\n”,x,i); } • 强制类型转换运算符 • 可以将一个表达式转换成所需类型 • 形式 (类型名)(表达式) 类型名与表达式都应用括号括起来 例(double)a (int)(x+y) 说明:强制类型转换时,得到一个所需类型 的中间变量,原变量的类型未发生变化 运行结果: x=3.600000,i=3 < >
自增、自减运算符++ -- 作用:使变量值加1或减1 种类: 前置 ++i, --i (先执行i+1或i-1,再使用i值) 后置 i++,i-- (先使用i值,再执行i+1或i-1) 例 j=3; k=++j; j=3; k=j++; j=3; printf(“%d”,++j); j=3; printf(“%d”,j++); a=3;b=5;c=(++a)*b; a=3;b=5;c=(a++)*b; //k=4,j=4 //k=3,j=4 //4 //3 //c=20,a=4 //c=15,a=4 < >
自增、自减运算符++ -- • 作用:使变量值加1或减1 • 种类: • 前置 ++i, --i (先执行i+1或i-1,再使用i值) • 后置 i++,i-- (先使用i值,再执行i+1或i-1) • 说明: • ++ -- 不能用于常量和表达式,如5++,(a+b)++ • ++ --结合方向: 自右向左 • 优先级: • 例 -i++ -(i++) • i=3; printf(“%d”,-i++); //-3 • 例 -i++ • i=3; printf(“%d”,-i++);
表达式使用中的问题说明 • 注意编译系统的调用顺序 例设i=3;求(i++)+(i++) +(i++) 有的系统值为9,有的为12 turboc系统中得到9 (++i)+(++i) +(++i) • 运算符的组成 自左至右尽可能多的将若干个字符组成一个运算符 • 实参的求值顺序 printf(“%d,%d”,i,i++);(i的值为3) 有的系统值为3,3有的为4,3 turboc系统中得到4,3
赋值运算符和表达式 赋值运算符 符号: = 格式: 变量标识符=表达式 作用:将一个数据(常量或表达式)赋给一个变量 • 类型转换 • 实型数据赋给整型变量时,舍弃实数的小数部分 int i;i=3.56;i的值为3,以整数形式存储 • 将整型数据赋给单、双精度变量时,数值不变,补足有效数字,以浮点数形式存储到变量中。 float f;f=23;转换成23.00000存储 double f;f=23;转换成23.00000000000000存储 注意:单、双精度变量的有效数字的位数 < >
0 1 0 1 0 1 1 1 0 0 1 1 1 0 0 1 1 1 1 0 0 1 1 0 • 类型转换 • 将一个double数据赋给float变量时,截取其前面7位有效数字,存放到存储单元中。 注意:数值范围不能溢出 • 将一个float数据赋给double变量时,数值不变,有效位数扩展到16位,以64位存储。 • 字符型数据赋给整型变量 • 字符为无符号量时,将字符的8位放到整型变量的低8位,高8位补零。 • 若为有符号字符,最高位为零,则整型变量的高8位补零 c=‘\376’ < >
0 1 0 1 1 0 0 0 1 0 1 1 1 1 1 0 1 0 1 1 1 1 1 1 1 1 0 1 1 0 0 0 0 0 0 1 1 1 1 0 0 1 0 0 1 0 0 1 • 类型转换 • 若字符最高位为1,则高八位全部补1。 注意:目的是使数值保持不变 • 将一个int、short、long数据赋给char变量时,只将其低8位原封不动送到char型变量。 c=‘\376’ i=289 < >
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 • 类型转换 • 将int型数据赋给long变量时,进行符号扩展,将整型数的16位送到long型低16位中,如果int为正值,则long高16位补零,如果int为负值,则高16位补1。 • 将一个long数据赋给int变量时,将其低16位原封不动送到整型变量。 • 将unsigned int型数据赋给long型变量时,高位补零 • 将一个unsigned类型数据赋给一个占字节数相同的整型变量,将unsigned型变量的内容原样送到非unsigned变量中。若为有符号字符,最高位为零,则整型变量的高8位补零。 注意:有可能出现数据错误 < >
a b 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 • 类型转换 unsigned int a=65535; int b; b=a; 注意:根据补码知识,b的值为-1。 • 将非unsigned型数据赋给长度相同的unsigned型变量,也是原样照赋。 例2.9 有符号数据传送给无符号变量 main() { unsigned a; int b=-1; a=b; printf(“%u”,a); } 不同类型的整型数据间的赋值: 按存储单元中的存储形式直接传送 运行结果: 65535 < >
复合的赋值运算符 在“=”前加上其他运算符,可构成复合的运算符 a+=3 等价于 a=a+3 x*=y+8 等价于 x=x*(y+8) x%=3 等价于 x=x%3 为便于记忆,可以这样理解 a+=b (a为变量,b为表达式) a+=b (将有下划线的移到“=”右侧) a=a+b (在“=”左侧补上变量名a) 10种复合赋值运算符 +=,-=,*=,/=,%=,<<=,>>=,&=,∧=,|= < >
赋值表达式 由赋值运算符将一个变量和一个表达式连接起来的式子 形式 〈变量〉〈赋值运算符〉〈表达式〉 求解过程 将赋值符右侧的表达式的值赋给左侧的变量 • 说明: • 结合方向:自右向左 • 左侧必须是变量,不能是常量或表达式 • 赋值表达式的值与变量值相等,且可嵌套 • 例 3=x-2*y; • a+b=3; • 赋值表达式也可以包含复合的赋值运算符 例: a=b=c=5 a=(b=5) a=5+(c=6) a=(b=4)+(c=6) a=(b=10)/(c=2) 例: int a=2; a%=4-1; a+=a*=a-=a*=3; 例: a=12; a+=a-=a*a //a=-264 等价于a=a+(a=a-(a*a)) //a=0 等价于a=a+(a=a*(a=a-(a=a*3))) < >
逗号运算符和表达式 形式:表达式1,表达式2,……表达式n 结合性:从左向右 求值顺序:表达式1,表达式2,……表达式n 逗号表达式的值:等于表达式n的值 用途:常用于循环for语句中 //a=15,表达式值60 • 例 a=3*5,a*4 • a=3*5,a*4,a+5 • 例 x=(a=3,6*3) • x=a=3,6*a • 例 a=1;b=2;c=3; • printf(“%d,%d,%d”,a,b,c); • printf(“%d,%d,%d”,(a,b,c),b,c); //a=15,表达式值20 //赋值表达式,表达式值18,x=18 //逗号表达式,表达式值18,x=3 //1,2,3 //3,2,3 < >
逗号运算符和表达式 • 形式:表达式1,表达式2,……表达式n • 结合性:从左向右 • 求值顺序:表达式1,表达式2,……表达式n • 逗号表达式的值:等于表达式n的值 • 用途:常用于循环for语句中 例: main() { int x,y=7; float z=4; x=(y=y+6,y/z); printf("x=%d\n",x); } 运行结果:x=3 < >
main(){char a=176,b=219;printf("%c%c%c%c%c\n",b,a,a,a,b);printf("%c%c%c%c%c\n",a,b,a,b,a);printf("%c%c%c%c%c\n",a,a,b,a,a);printf("%c%c%c%c%c\n",a,b,a,b,a);printf("%c%c%c%c%c\n",b,a,a,a,b); }作业: P41 2.3(2)、(5),2.6,2.7,2.8,2.9,2.10,2.11,2.12