1、语言程序设计,数据类型、运算符和表达式,一、C语言的数据类型,二、C语言的变量和常量,2.1 常量和符号常量,1、常量: 在程序运行过程中,其值不能被改 变的量。每种数据类型都有常量,也都有变量。如整型常量、浮点型常量.例如: 12、4 、-67 或 3.14 5.6 或 a 、d从上可以看出常量可以是不同类型的.2、常量分为两种直接常量和符号常量。直接常量直将数值直接使用,如:a=b*10; 当用一个标志符代表一个常量时,称为符号常量.,2.1 常量和符号常量,1、常量: 在程序运行过程中,其值不能被改 变的量。每种数据类型都有常量,也都有变量。如整型常量、浮点型常量.例如: 12、4 、-
2、67 或 3.14 5.6 或 a 、d从上可以看出常量可以是不同类型的.2、常量分为两种直接常量和符号常量。直接常量直将数值直接使用,如:a=b*10; 当用一个标志符代表一个常量时,称为符号常量.,上例中的PRICE 就称为符号常量;凡在程序中出现的PRICE 都代表30。PRICE=PRICE+5; /*正确否*/ 一般情况下,符号常量名用大写、变量用小写。,例: #define PRICE 30 main() int num, total; num=10; total=num* PRICE; printf(“total=%d“,total); ,3、符号常量的声明和使用 一般放在程序的
3、前端,与#include 在一块: #define 符号常量名 值 如:#define Zero 0好处:含义清楚 (#define Second 60) 一改全改 (#define PI 3.14),2.2 变量,在程序运行过程中,其值可以改变的量称为变量。 一个变量应该有一个变量名,并且在内存中占据一定的的存储单元用来存放变量的值。注意:变量名与变量值的区别,在C语言中,要求对所有用到的变量作强制定义,即“先定义、后使用”。因为:1、 编译程序不能翻译未定义变量。2、 编译程序在编译时根据变量类型确定存储单元的数量并分配空间3、编译程序在编译时根据变量类型进行语法检查。例,整型变量a、b可
4、以进行“求余”运算 a % b;若把a、b定义为实数,则上述运算非法。,main() int i, studentNo;i=5; studentno=5; /*错在哪里*/j=3; /*错在哪里*/ ,一条变量说明语句由数据类型和其后的一个或多个变量名组成。变量说明的形式如下: 类型 ; 这里类型是指Turbo C2.0的有效数据类型。变量表是一个或多个标识符名, 每个标识符之间用“,“分隔。例如: int iint i, j, k; char c, str5, *p;,所谓标识符是指常量、变量、语句标号以及用户自定义函数的名称。Turbo C 2.0标识符的定义十分灵活。作为标识符必须满足以
5、下规则:1.所有标识符必须由一个字母(az, AZ)或下划线(_)开头;2.标识符的其它部分可以用字母、下划线或数字(09)组成;3.大小写字母表示不同意义, 即代表不同的标识符;4.标识符只有前32个字符有效(Turbo C)5.标识符不能使用Turbo C2.0的关键字。,2.3标识符,下面举出几个正确和不正确的标识符: 正确-不正确 smart-5smart _decision-bomb? key_board-key.board FLOAT-float,三、整型数据,整型常量即整常数按不同的进制区分, 整型常数有三种表示方法: 十进制数: 以非0开始的数 如:220, -560, 459
6、00 八进制数: 以0开始的数 如:06; 0106, 05788 十六进制数: 以0X或0x开始的数 如:0X0D, 0XFF, 0x4e,3.1.整型常量,main()int i;i=11;printf(“i=%dn”,i);i=011;printf(“i=%dn”,i);i=0x11;printf(“i=%dn”,i);i=0X11;printf(“i=%dn”,i); 程序的输出结果是多少?,注意: 可在整型常数后添加一个“L“或“l“字母表示该数为长整型数,如22L, 0773L, 0Xae4l。 另外, 所有整数的缺省类型是int,可在整型常数后添加一个“L“或“l“字母表示该数为
7、长整型数, 如 22L,0773L, 0Xae4l。 若加上一个“u“或“U“字母表示该数为无符号整型数,如27u, 0400u, 0xb8000000u。 若加上一个“ul“或“UL“字母表示该数为无符号长整型数,如 27ul, 0400UL, 0xb8000000UL。 当整数的值超出int类型所能表示的范围时称为整数溢出。,1整型变量的分类:加上不同的修饰符, 整型变量有以下几种类型;C语言标准没有规定整型变量在计算机内存中所占的字节数,它与具体的机器和操作系统有关:,3.2、整型变量,2. 整型变量的定义 可以用下列语句定义整型变量: int a, b; /*a、b被定义为有符号短整型
8、变量*/ unsigned long c; /*c被定义为无符号长整型变量*/ unsigned short c,d; /*指定变量c、d为无符号短整型 */ long e,f; /* 指定变量e、f为长整型*/程序中在函数的开头部分定义变量。,main() int a,b,c,d; /* 指定变量a、b、c、d为整型 */unsigned u; /* 指定变量u为无符号整型 */a = 12; b = -24; u = 10;c = a + u; d = b+u;printf(“a+u = %d, b+u = %dn“, c,d); 程序运行显示:a+u = 22, b+u = -14,3.
9、 整型变量的溢出,main()int i,j;unsigned k,l,m;i=32767;j=i+1;l=65535u;m=l+2;printf(“j=%dn“,j);printf(“l=%un“,l);printf(“m=%un“,m); ,象这类问题体现了C语言灵活性所带来的副作用。 这种错误系统不给提示,由程序员自己控制。,四、实型数据,实数(real)又称为浮点数(float),有两种表达方式:普通(十进制)方式:0.123、 .123、 123.0、 123.、 0.0(必须有小数点) 指数方式:123e3或123E3、123E-2 注意:字母e(或E)之前必须有数字e后面指数必须
10、为整数 规范化指数形式:e前的小数部分中,小数点左边只能有一位非0数字。如下面例子应为: 1.23e5错误:0.123e6,4.1 实型常量,4.2 实型变量,精确程度,例: float x,y; /* 指定x、y为单精度实型变量 */ double z; /* 指定z为双精度实型变量 */ 实型常量不分float和double。 问题:如何用图示的方法表示这些变量的内存空间?,4.3 实型变量的误差与精度,main()float a,b;a=123456.789e5;b=a+20;printf(“%fn”,a);printf(“%fn”,b); 注意输出结果,main()float a;do
11、uble b;a=111111.111;b=111111.111;printf(“%fn”,a);printf(“%fn”,b); 注意输出结果,五、字符型数据,用单引号(撇号)括起来的一个字符。 如:a、x、D、?、$。 注意,a和A是不同的字符常量。 因为C语言区分大小写。以“”开头的字符序列,称为“转义序列”。 “”使其后面的字符变为另外的意义。见下表。,5.1 字符常量,转义序列主要用来控制打印机和屏幕输出。 例:printf(“n sum is %dnn“,sum);比较下面两句的区别: printf(“this is a “test”); /*出错*/ printf(“this i
12、s a “test”); /*输出:this is a “test”*/,char c1,c2; /* 定义c1、c2为字符变量 */ c1 = a; c2 = b;字符变量在内存中占一字节。问题:如何用图示的方法表示这些变量的内存空间?,5.2 字符变量,字符在内存中以ASCII码存放。,5.3 字符数据在内存中的存储形式及其使用方法,main() char c1,c2;c1 = A; c2 = B; printf(“%c %c“,c1+32,c2+32); ,该例的输出是:,a b,main() char c1,c2;c1 = a; c2 = b;c1 = c1 - 32; c2 = c2
13、 - 32; printf(“%c %c“,c1,c2); ,C语言允许字符和整数之间进行运算,字符常量: 单引号括起来的一个字符。 字符串常量:双引号括起来的字符序列 (0N个字符)。如: “How do you do.“, “CHINA“, “a“, “$123.45“ 字符串常量在内存中的存放: 每一个字符均以其ASCII码存放,且最后添加一个“空字符”(二进制00000000,记为NULL或0。字符0在内存中存0x30即00100000)。,5.4 字符串常量,例:字符串常量“CHINA”存放在内存中的情况是:(6字节存储器空间,不是5字节),因此,字符a和字符串“a“的区别是: 字符
14、a :1字节(值为97) 字符串“a“:2字节(值为97,0),5.5 字符与整型的相互转换,main( ) char c1,c2; c1=a; c2=b; printf (“c1=%c,c2=%c n”,c1,c2); printf (“c1=%d,c2=%d n”,c1,c2); /*问题:结果如何*/,六、变量赋初值,为什么要给变量赋初值?(教室不打扫) 因为分配的内存空间可能有一个脏数据。如果不赋初值,默认初始值就是这个脏数据。(举例说明)1.定义的同时给变量赋初值 如:int a=3; float b=3.1415;char c=x; 2.定义变量时,可以对其中的一部分变量赋初值.如
15、: int a=3, b, c, d=8;,3.把一个值赋给不同变量时,要分别进行。如不应写为:int a=b=c=3; 而应写为: int a=3,b=3,c=3; 4.初始化是在程序运行时,执行本函数时赋以初值的。 即不是编译时赋以初值的。如:int a=3; 相当于:int a; a=3; int a,b,c=5; 相当于:int a,b,c; c=5;,七、各类数值型数据间的混合运算,在C语言中,整、实、字符型数据间可以混合运算,如: 10 + a + 1.5 - 8765.1234 * b1、不同类型数据间进行运算时,要转换成同一类型 转换过程中,低类型向高类型靠拢,然后进行运算,不
16、同类型之间转换如下图所示,横向左箭头为必转,纵向箭头表示有条件类型转换。,例: char数据在运算前必定转换为int数据; int数据可以转换为unsigned数据; float数据在运算前必定转换为double数据(即使两个float相加);int数据可以转换为double数据(若另外一个运算数据为double),(直接转换,不需先转换为unsigned,long,再转换为double)。,上式的运算次序是: 进行10+a运算。先将a转换为整数97,运算结果为整数107。 进行i*f运算。先将i和f均转换为double类型(实运算过程总是使用double类型,仅在把结果存入存储器时,才可能使
17、用float类型),运算结果是double类型。 整数107与i*f的积相加。先将整数107转换为double类型(107.0),运算结果是double类型。 进行d/e运算。先将long e转换为double类型,运算结果是double类型。 进行-运算,结果为double类型。,八、算术运算符和算术表达式,8.1 C运算符简介,8.2算术运算符和算术表达式,1、基本的算术运算符 +:加法或正值运算符,如:2+3 、+5 -:减法或负值运算符,如:8-3 、-6 *:乘法运算符, 如:3*5 /: 除法运算符,则可以是整或实型数据。如5/3 %:求余运算符,两侧必是整型数据。如7%4注:-5
18、/3 = -1(余-2) 或 -2(余+1),Turbo C 取-1结果(“向零取整”)。,2、算术表达式和运算符的优先级与结合性算术表达式: 如:a*b/c-1.5+a在C语言中,运算符共有15个优先级,其中算术运算符的优先级是: *、/ 、%(3级) + 、-(4级)请见P375376 算术运算符的结合方向:从左向右,注意:对于运算符的结合方向,只需记住三种运算符是自右向左的,其余都是自左向右的。这三种运算符是: 单目运算符、 三目运算符(only one)、 赋值运算符(不计算好如何赋值?)例: a = b + c 由于赋值运算符=为右结合, 先执行右边的b+c,再赋值给a。,8.3、强
19、制类型转换运算符,一般形式: (类型名) (表达式) 如:(double)a 将a转换为double型 (int)(x+y) 将x+y的值转换为整型 (float)(5%3) 将5%3的值转换成单精度实型 说明:1.(int)(x+y) 与(int)x+y 意义不同 2. 类型转换后得到一个中间值,而原来变量本身的类型没有发生变化。 3.(int)x不要写成int(x); /*C语言中不行,c+允许*/,main( ) float x , i; x=3.6; i=(int) (x); printf (“x=%f, i=%fn”,x,i); 运算结果:x=3.600000, i=3.000000
20、 思考:程序运行期间,x,i的类型和值发生变化没有?,8.4、自增、自减运算符,+:增1运算符,使变量值增1。 记忆:+在前,先加;在后,后加-:减1运算符,使变量值减1。 如:+i ,-i:在使用变量i之前,先使变量i加(减)1。 i+,i-:在使用变量i之后,使变量i值加(减)1。,main( ) int i,j; i=3;j=+i; printf (“i=%d,j=%dn”,i,j); 运算结果:i=4,j=4,main( ) int i,j; i=3;j=i+; printf (“i=%d,j=%dn”,i,j); 运算结果:i=4,j=3,说明: 1.+,- -运算符只能用于变量,而
21、不能用于常量和表达式。 如a+,b-是正确的,而5+,(x+y)- -却是错误的。 2.+,- -运算符的结合方向是从右向左。,main( ) int i,j; i=3;i+;j=i;printf (“i=%d,j=%dn”,i,j); 运算结果?,main( ) int i; i=3; printf (“i1=%dn”,-i+); printf (“i2=%dn”,i); ,运算结果:i1=-3 i2=4,注意:结合性自右向左(单目运算符),main( ) int i; i=3; printf (“i1=%dn”,-+i); printf (“i2=%dn”,i); 运算结果:i1= -4
22、i2=4,main( ) int i=3,j=3,k,q; k=(i+)+(i+)+(i+); q=(+j)+(+j)+(+j); printf (“i=%d,j=%d,k=%d,q=%dn”,i,j,k,q); TC运算结果:i=6,j=6,k=9,q=18,1)、无需深究的问题 表达式中的子表达式的求值顺序各编译系统是有差别的。,2)在C语言中运算符的确定 在由多个字符组成的表达式中,应尽可能多地从左向右将若干个字符组成一个运算符。 如:i+j 其结合性是:(i+)+j 不是:i+(+j) 。,3)printf 函数输出实参的顺序 如:int i=3; printf (“%d,%dn”,i
23、,i+); 有的系统按从左到右的顺序求值,输出结果是:3,3 而Turbo C 是按从右到左顺序求值,输出结果是:4,3 结论:不写别人甚至自己都看不懂的程序,也不写那些不知道系统会怎样运行的程序.,九、 赋值运算符和赋值表达式,9.1、赋值运算符,“=”是赋值号,也是赋值运算符 功能:将赋值号右边表达式的值赋给赋值号左边的变量,赋值号同时含有计算的功能。 如:a=3; b=x*y; a,b变量中原来不管存放什么值,执行赋值语句后,新值将取代旧值,9.2、类型转换,(1)实型数据赋给整型变量时,舍去实型数据的小数部分。如: int i; i=3.56; 结果i的值为3 (2)整型数据赋给实型变
24、量时,数值不变,但以浮点形式存放于内存。 如: float a=23; 先将23转换成23.000000,然后送a中。 double b=23; 先将23转换为23.00000000000000,然后送b中,(3)double型数据赋给float变量 截取其前面的7位有效数字,存放到float单元,应注意数值范围不能溢出 如:float f; double d=123.45678e65; f=d; 由于数据溢出,f将得到错误的值 float 数据赋给double变量时,数值不变,有效位扩展到16位。 (4)字符型数据赋给整型变量,(5)int, short, long型数据赋给char变量,则
25、将其低位赋给char型变量 (6)long型数据赋给int型变量,将long型数据的低16位赋给int型变量 (7)将unsigned int型数据赋给long型变量时:将unsigned int型数据送到long int型变量的低16位,long int的变量高16位补0若无符号数据赋给相同长度的带符号的变量时,则原样赋给。 要注意数据的有效位占据符号位,若最高位为1,则赋值后新变量的值成负。,(8)将带符号的数赋给长度相同的无符号变量 原样赋给 main( )unsigned int a; int b= -1; a=b; printf (“a=% u,b=%dn”,a,b); 运算结果:
26、a=65535,b= -1,9.3、复合的赋值运算符,在赋值号前加其它运算符,可以构成复合运算符。 如: a=a+b 等价于 a+=b x=x*(y+8) 等价于 x*=y+8 x=x%3 等价于 x%=3 为了便于记忆,将赋值号左边移到赋值号右边,赋值号 左边再补上变量名。 如:a+= b a+复制到=右边,等号左边补操作数aa=a+b 其中a是变量,b是表达式 x*= y+8 - x=x*(y+8) 而不是x=x*y+8C语言中,有十个二元运算符:+、-、*、/、%、 、&、| 可与赋值号一起构成复合运算符; 其优点是:简化程序,提高编译效率。,9.4、赋值表达式,由赋值运算符将一个变量和
27、一个表达式连接起来的式子。 (1)一般形式: a=5; (2)赋值表达式求解过程: 计算赋值号右边表达式的值,然后赋给左边的变量。 如:a=3+5 在C语言中,表达式又可以是赋值表达式,如a=(b=5); 其中 b=5是赋值表达式,其值是5,因此a的值是5,整 个表达式的值是5。,(3)赋值运算符的结合顺序:从右向左 因此:a=(b=5) 与 a=b=5 是等价的。 赋值表达式的例子: a=b=c=5 表达式的值为5,a,b,c的值为5。 a=5+(c=6) 表达式的值为11,a的值为11,c的值为6。 a=(b=4)+(c=6) 表达式的值为10,a的值为10,b为4,c为6。 a=(b=1
28、0)/(c=2) 表达式的值为5,a的值为5,b为10,c为2。,(4)赋值表达式也可以包含复合的赋值运算符 main( ) int a=12, b; b=(a+=a-=a*a); printf (“a=%d, b=%dn”,a,b); 运算结果:a= -264,b= -264 a + = a- = a*a a=a-a*a 12-12*12 -132 a=a+(-132) -132+(-132) -264,十、逗号运算符和逗号表达式,逗号运算符:,又称“顺序求值运算符”; 优先级最低逗号表达式:用逗号将两个表达式连接起来的式子。 形式:表达式1,表达式2 求解过程:先求表达式1的值,再求表达式
29、2的值,整个表达式的值是表达式2的值。 注:表达式1和表达式2又可以分别由若干个逗号表达式 组成。因此,逗号表达式又可扩展为: 表达式1, 表达式2, 表达式n,如: 3*5,68 表达式14 (a=3*5,a*4) 变量a15 表达式60 main( )int a,b; b=(a=3*5,a*4),a+5); printf (“a=%d,b=%dn”,a,b); 运算结果: a=15,b=20,1.逗号运算符是一个顺序求值运算符 main( ) int x,a=1,b=2,c=3; x=a,b,c; printf (“x=%dn”,x); 运算结果:x=1 main( ) int a=1,b=2,c=3,x; x=(a,b,c); printf (“x=%dn”,x); 结果:x=3,2.并非所有出现“,”的地方都是逗号运算符,如函数中 的参数分隔符 main( ) int a=1,b=2,c=3; printf (“%d,%d,%dn”,a,b,c); printf (“%d,%d,%dn”,(a,b,c),b,c); 运算结果: 1,2,3 3,2 ,3,