第 3章 数据类型、运算符与表达式
3.1 程序设计概述
3.2 常量和变量
3.3 整型数据
3.4 实型数据
3.5 字符型数据
3.6 算术运算与算术表达式
3.7 赋值运算与赋值表达式
3.8 C语言特有的运算和运算符
[Return]
3.1 程序设计概述一个程序应包括对数据的描述和对数据处理的描述。
对数据的描述,即数据结构。数据结构是计算机学科的核心课程之一,有许多专门著作论述,本课程就不再赘述。
在 C语言中,系统提供的数据结构,是以数据类型的形式出现的。
基本类型数据类型构造类型指针类型空类型
[Return]
整形字符型实型(浮点型) ——单精度型、双精度型枚举类型数组类型结构体类型共用体类型
3.2 常量和变量
3.2.1 常量
1.常量的概念在程序运行过程中,其值不能被改变的量称为常量。
2.常量的分类
( 1)整型常量,12,0,-3
( 2)实型常量,4.5,-1.456
( 3)字符常量:‘ a‘、’ g‘、’ h‘
( 4)符号常量,#define PRICE 30?
常量的类型,可通过书写形式来判别。
3.2.2 变量
1.变量的概念在程序运行过程中,其值可以被改变的量称为变量 。
2.变量的两个要素
#define PRICE 30
Main ( )
{int num,total;
Num=10;
Total=num*PRICE;
Print(―total=%d‖,total);
}
(1)变量名 。 每个变量都必须有一个名字 ── 变量名 。
(2)变量值 。 变量值存储在内存的存储单元中 。 在程序中,通过变量名来引用变量的值 。
3,标识符命名规则
( 1) 有效字符:只能由字母,数字和下划线组成,且以字母或下划线开头 。
( 2) 有效长度:随系统而异,但至少前8个字符有效 。
如果超长,则超长部分被舍弃 。
例如,由于 student_name和 student_number的前8个字符相同,有的系统认为这两个变量,是一回事而不加区别 。
在 TC V2.0中,变量名 ( 标识符 ) 的有效长度为1~32
个字符,缺省值为32 。
A
10
( 3) C语言的关键字不能用作变量名 。
( 4) C语言对英文字母的大小敏感,即同一字母的大小写,被认为是两个不同的字符 。 习惯上,变量名和函数名中的英文字母用小写,以增加可读性 。
思考题,在 C语言中,变量名 total与变量名 TOTAL、
ToTaL,tOtAl等是同一个变量吗?
标识符命名的良好习惯 ──见名知意,
所谓,见名知意,是指,通过变量名就知道变量值的含义 。 通常应选择能表示数据含义的英文单词 ( 或缩写 ) 作变量名,或汉语拼音字头作变量名 。
例如,name/xm( 姓名 ),sex/xb( 性别 ),age/nl( 年龄 ),salary/gz( 工资 ) 。
4.变量的定义与初始化在C语言中,要求对所有用到的变量,必须先定义,后使用; 且称在定义变量的同时进行赋初值的操作为变量初始化 。
( 1) 变量定义的一般格式数据类型 变量名 [,变量名 2…… ];
例如,float radius,length,area;
( 2) 变量初始化的一般格式
[存储类型 ] 数据类型 变量名 [=初值 ][,变量名 2[=初值
2]…… ];
例如,float radius=2.5,length,area;
int x;
x=5;
[Return]
3.3 整型数据
3.3.1 整型常量
1,三种表示形式:
整型常量即整常数,在C语言中可用三种形式表示:
( 1) 十进制 。 例如 10,36。
( 2) 八进制 ( 以数字0开头 ) 。 例如 012。
( 3) 十六进制 ( 以数字0 +小写字母 x开头 ) 。 例如
0x36。
3.3.2 整型变量
1.整形数据在内存中的存储形式:数值是以补码形式表示的。
正数?是其本身负数?将该数的绝对值的二进制形式,按位取反再加 1
2.分类根据占用内存字节数的不同,整型变量又分为4类:
( 1)基本整型(类型关键字为 int)。
( 2)短整型(类型关键字为 short [int])。
( 3)长整型(类型关键字为 long [int])。
( 4)无符号整型。无符号型又分为无符号基本整型
( unsigned [int])、无符号短整型( unsigned short)和无符号长整型( unsigned long)三种,只能用来存储无符号整数。
3.占用内存字节数与值域上述各类型整型变量占用的内存字节数,随系统而异。在 16
位操作系统中,一般用2字节表示一个 int型变量,且 long型(4
字节) ≥ int型(2字节) ≥ short型(2字节)。 显然,不同类型的整型变量,其值域不同。
4.类型匹配规则类型匹配规则为:一个整型常量,可以赋给能容纳下其值的整型变量 。
例如,其值在 -2 15 --( 2 15 -1 ) 的整型常量,可以赋给 int
型变量和 long int型变量;其值在 -2 31 ——( 2 31 -1 ) 的整型常量,就只能赋给 long int型变量 。
注意,常量无 unsigned型。但一个非负整型常量,只要它的值不超过相应变量的值域(即取值范围),也可以赋给
unsigned型变量。
类型 其值范围 赋给的变量
Int -32768~+32767 Int,long int
Long int -2147483648~+2147483647
如,12345L,0L
Long int
[Short] int -32768~+32767 Int,shot int
Unsigned int 以补码形式存储 如,1234u
5.不同种类的整形数据可以进行算术运算。
例,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);
}
6.整形数据的溢出:
Main( )
{int a,b;
a=32767;
b=a+1;
printf(“%d,%d”,a,b);
}
[Return]
运行结果,a+u=32,b+u=-14
运行结果,32767,-32768
3.4 实型数据
3.4.1 实型变量
C语言的实型变量,分为两种:
( 1)单精度型。类型关键字为 float,一般占4字节(32
位)、提供7位有效数字。其值范围,-3.4× 10-38——3.4× 1038
( 2)双精度型。类型关键字为 double,一般占8个字节、提供 5~16位有效数字。其值范围,-1.7× 10-308——1.7× 10308
( 3)长双精度型。类型关键字为 long double,一般占 16个字节、提供 18~19位有效数字。其值范围,-1.2× 10-4932——
1.2× 104932
3.4.2 实型常量
1,表示形式实型常量即实数,在C语言中又称浮点数,其值有两种表达形式:
( 1)十进制形式。例如 3.14,9.8。
( 2)指数形式,<尾数 >E( e) <整型指数 >。例如 3.0E +5等。
但注意字母 E之前必须有数字,且 E后面的指数必须为整数。
2,关于类型实型常量分 float型和 double型。一个实型常量,可以赋给一个实型变量( float型或 double型)。
[Return]
3.实型数据在内存中的存储形式
4.实型数据的舍入误差:
main()
{float a,b;
a=123456.789e5;
b=a+20;
printf("%f\n%f\n",a,b);
}
+,564812 1
数符号 小数部分 指数
+,564812 101?5.64812
运行结果,12345678848.000000
12345678848.000000
a,b的值相同。由于有效数字是 7位。
因此应避免一个很大的数与很小的数相加、减,否则丢失很小的数。
3.5 字符型数据
3.5.1 字符常量
1.字符常量的定义:用一对单引号括起来的单个字符,称为字符常量。例如,‘ A‘,‘ 1 ’,‘ + ’ 等。
2.转义字符:C语言还允许使用一种特殊形式的字符常量,就是以反斜杠,\ ‖开头的转义字符。见表注意,如果反斜杠或单引号本身作为字符常量,必须使用转义字符,‘ \\‘,‘ \‘?。
[案例 3.1] 用转义字符输出可打印字符和不可打印字符。
/*案例代码文件名,AL3_2.C*/
/*程序功能:用转义字符输出可打印字符和不可打印字符 */
main()
{printf(―\x4F\x4B\x21\n‖);/* 等价于 printf(―OK!\n‖); */
printf(―\x15 \xAB\n‖);
} 程序运行结果如下:
OK!
§? [程序演示 ]
字符形式 含义 ASCII代码
\n 换行,将当前位置移到下一行开头 10
\t 水平制表(跳到下一个 TAB位置) 9
\b 退格,将当前位置移到前一列 8
\r 回车,将当前位置移到本行开头 13
\f 换页,将当前位置移到下页开头 12
\\ 反斜杠字符,\‖ 92
\' 单撇号字符 39
\" 双撇号字符 34
\ddd 1到 3位 8进制数所代表的字符
\xhh 1到 2位 16进制数所代表的字符转义字符及含义
3.5.2 字符变量字符变量的类型关键字为 char,一般占用 1字节内存单元。
1.变量值的存储字符变量用来存储字符常量。将一个字符常量存储到一个字符变量中,实际上是将该字符的 ASCII码值(无符号整数)存储到内存单元中。
例如,char ch1,ch2; /*定义两个字符变量,ch1,ch2*/
ch1=‘a‘; ch2=‘b‘; /*给字符变量赋值 */
2.特性字符数据在内存中存储的是字符的 ASCII码 ── 一个无符号整数 ((0-255),其形式与整数的存储形式一样(如图 2-4
所示),所以C语言允许字符型数据与整型数据之间通用。
( 1)一个字符型数据,既可以字符形式输出,也可以整数形式输出。
( 1)一个字符型数据,既可以字符形式输出,也可以整数形式输出。
[案例 3.2] 字符变量的字符形式输出和整数形式输出 。
/*案例代码文件名,AL3_3.C*/
/*程序功能:用字符形式和整数形式输出字符变量 */
main()
{ char ch1,ch2;
ch1='a'; ch2='b';
printf(―ch1=%c,ch2=%c\n‖,ch1,ch2);
printf(―ch1=%d,ch2=%d\n‖,ch1,ch2);
}
程序运行结果,ch1=a,ch2=b
ch1=97,ch2=98 [程序演示 ]
( 2)允许对字符数据进行算术运算,此时就是对它们的 ASCII码值进行算术运算。
[案例 3.4] 字符数据的算术运算。
/*案例代码文件名,AL3_4.C*/
/*程序功能:字符数据的算术运算 */
main()
{ char ch1,ch2;
ch1=?a‘; ch2=?B‘; /*字母的大小写转换 */
printf(―ch1=%c,ch2=%c\n‖,ch1-32,ch2+32);
/*用字符形式输出一个大于 256的数值 */
printf("ch1+200=%d\n",ch1+200);
printf("ch1+200=%c\n",ch1+200);
printf("ch1+256=%d\n",ch1+256);
printf("ch1+256=%c\n",ch1+256);
}
程序运行结果:
ch1=A,ch2=b
ch1+200=297
ch1+200=)
ch1+256=353
ch1+256=a [程序演示 ]
3.5.3 字符串常量
1.字符串常量的概念和字符串长度字符串常量是用一对双引号括起来的若干字符序列。
字符串中字符的个数称为字符串长度。长度为 0的字符串(即一个字符都没有的字符串)称为空串,表示为
,” (一对紧连的双引号)。
例如,,How do you do.‖、,Good morning.‖等,都是字符串常量,其长度分别为 14和 13(空格也是一个字符)。
如果反斜杠和双引号作为字符串中的有效字符,则必须使用转义字符。
例如:( 1) C:\msdos\v6.22 → "C,\\msdos\\v6.22"
( 2) I say:"Goodbye!" → "I say,\"Goodbye!\"―
2.字符串的存储
C语言规定:在存储字符串常量时,由系统在字符串的末尾自动加一个‘ \0‘作为字符串的结束标志。
注意,在源程序中书写字符串常量时,不必加结束字符‘ \0‘,否则画蛇添足。
如果有一个字符串为,CHINA‖,则它在内存中的实际存储如下所示:
最后一个字符 '\0'是系统自动加上的,它占用
6字节而非5字节内存空间。
C H I N A \0
综上所述,字符常量 'A'与字符串常量 "A"是两回事:
( 1) 定界符不同:字符常量使用单引号,而字符串常量使用双引号;
( 2) 长度不同:字符常量的长度固定为 1,而字符串常量的长度,可以是 0,也可以是某个整数;
( 3) 存储要求不同:字符常量存储的是字符的 ASCII
码值,而字符串常量,除了要存储有效的字符外,还要存储一个结束标志 ’ \0‘。
[Return]
3.6 算术运算符与算术表达式在C语言中,除控制语句和输入输出函数外,其它所有基本操作都作为运算符处理。
1.五种基本算术运算符
+,-(减法 /取负),*,/,%(求余数)
( 1)关于除法运算 /
C语言规定:两个整数相除,其商为整数,小数部分被舍弃。例如,5 / 2 = 2。但出现负数时,结果向零靠拢。
例 -5/3=- 1,7/-3=-2。
( 2)关于求余数运算%
要求两侧的操作数均为整型数据,否则出错。
2.表达式和算术表达式
( 1) 表达式的概念用运算符和括号将运算对象 ( 常量,变量和函数等 ) 连接起来的,符合C语言语法规则的式子,称为表达式 。
单个常量,变量或函数,可以看作是表达式的一种特例 。 将单个常量,变量或函数构成的表达式称为简单表达式,其它表达式称之为复杂表达式 。
( 2) 算术表达式的概念表达式中的运算符都是算术运算符 。 例如,3 + 6 * 9、
(x + y) / 2 - 1等,都是算术表达式 。
良好的源程序书写习惯,在表达式中,在双目运算符的左右两侧各加一个空格,可增强程序的可读性 。
请比较表达式,(x + y) / 2 – 1‖与,(x+y)/2–1‖,您认为哪个的可读性更好一些?
3.运算符的优先级与结合性
( 1) C语言规定了运算符的优先级和结合性 。
所谓结合性是指,当一个操作数两侧的运算符具有相同的优先级时,该操作数是先与左边的运算符结合,还是先与右边的运算符结合 。
自左至右的结合方向,称为 左结合性 。 反之,称为 右结合性 。
结合性是C语言的独有概念 。 除 单目 运算符,赋值运算符和 条件 运算符是右结合性外,其它运算符都是左结合性 。
( 2) 表达式求值
1) 按运算符的优先级高低次序执行 。 例如,先乘除后加减 。
2) 如果在一个运算对象 ( 或称操作数 ) 两侧的运算符的优先级相同,则按C语言规定的结合方向 ( 结合性 )
进行 。
例如,算术运算符的结合方向是,自左至右,,即:
在执行,a – b + c‖时,变量 b先与减号结合,执行,a - b‖;
然后再执行加 c的运算 。
4.数据类型转换
( 1) 在C语言中,整型,实型和字符型数据间可以混合运算 ( 因为字符数据与整型数据可以通用 ) 。
如果一个运算符两侧的操作数的数据类型不同,则系统按,先转换,后运算,的原则,首先将数据自动转换成同一类型,然后在同一类型数据间进行运算 。 转换规则如下,高 double?float
long
unsigned
低 int?char,short
注意,箭头方向只表示数据类型由低向高转换,不要理解为 int型先转换成 unsigned型,再转换成 long型,最后转换成 double型 。
( 2) 除自动转换外,C语言也允许强制转换 。
数据类型强制转换的一般格式为:
(要转换成的数据类型 )(被转换的表达式 )
当被转换的表达式是一个简单表达式时,外面的一对圆括号可以缺省 。
例如,
(double)a ( 等价于 (double)(a)) /*将变量 a的值转换成 double型 */
(int)(x + y) /*将 x+y的结果转换成 int型 */
(float)5 / 2( 等价于 (float)(5)/2) /*将 5转换成实型,再除以 2( =2.5) */
(float)(5 / 2) /*将 5整除 2的结果 ( 2) 转换成实型
( 2.0) */
注意,强制转换类型得到的是一个所需类型的中间量,原表达式类型并不发生变化 。 例如,(double)a 只是将变量 a的值转换成一个
double型的中间量,其数据类型并未转换成 double型 。
[Return]
3.7 赋值运算与赋值表达式
1.赋值运算赋值符号,=‖就是赋值运算符,它的作用是将一个表达式的值赋给一个变量。
赋值运算符的一般形式为,变量 = 赋值表达式例如,x = 5
y = (float)5 / 2
如果表达式值的类型,与被赋值变量的类型不一致,
但都是数值型或字符型时,系统自动地将表达式的值转换成被赋值变量的数据类型,然后再赋值给变量。
思考题,假设变量 num的数据类型为 float,其值为 2.5,
则执行,num = (int)num‖后,num的值等于多少?
2.复合赋值运算复合赋值运算符是由赋值运算符之前再加一个双目运算符构成的 。
复合赋值运算的一般格式为:
变量 双目运算符 = 表达式
└──┬──┘
复合赋值运算符它 等价于,变量 = 变量 双目运算符 (表达式 )。
当表达式为简单表达式时,表达式外的一对圆括号才可缺省,否则可能出错 。
例如,x += 3 /*等价于 x=x+3 */
y *= x + 6 /*等价于 y=y*(x+6),而不是 y=y*x+6 */
X %=y+3 /*等价于 x=x%(y+3),而不是 x=x%y+3 */
C语言规定的 10种复合赋值运算符如下:
+=,-=,*=,/=,%=; /*复合算术运算符 ( 5个 ) */
&=,^=,|=,<<=,>>=; /*复合位运算符 ( 5个 ) */
3.赋值表达式由赋值运算符或复合赋值运算符,将一个变量和一个表达式连接起来的表达式,称为赋值表达式 。
( 1) 一般格式变量 (复合)赋值运算符 表达式
( 2) 赋值表达式的值任何一个表达式都有一个值,赋值表达式也不例外 。 被赋值变量的值,就是赋值表达式的值 。
例如,,a = 5‖这个赋值表达式,变量 a的值,5,就是它的值 。
A=(b=5)?b=5;a=b; (自右向左结合 )
A=b=c=5?a,b,c值均为 5。
Printf(―%d‖,a=b);赋值表达式可以出现在其他语句中 。 ( 输出,循环语句等 。 )
[Return]
3.8 C语言特有的运算和运算符
3.8.1 自增( ++)、自减(--)运算
1.作用自增运算使单个变量的值增1,自减运算使单个变量的值减1。
2.用法与运算规则自增、自减运算符都有两种用法:
( 1)前置运算 ──运算符放在变量之前:++变量、
--变量 ++i,--i,先使变量的值增(或减)1,然后再以变化后的值参与其它运算,即先增减、后运算。
( 2)后置运算 ──运算符放在变量之后:变量++、
变量--,i++,i--,变量先参与其它运算,然后再使变量的值增(或减)1,即先运算、后增减。
[案例 3.5] 自增,自减运算符的用法与运算规则示例 。
/*案例代码文件名,AL2_4.C*/
/*程序功能:自增,自减运算符的用法与运算规则示例 */
main()
{ int x=6,y;
printf("x=%d\n",x); /*输出 x的初值 */
y = ++x; /*前置运算 */
printf("y=++x,x=%d,y=%d\n",x,y);
y = x--; /*后置运算 */
printf("y=x--,x=%d,y=%d\n",x,y);
}
程序运行结果:
x=6
y=++x,x=7,y=7
y=x--,x=6,y=7 [程序演示 ]
思考题,如果将案例,y=++x;‖语句中的前置运算改为后置 ( y=x++;),,y=x--;‖语句中的后置运算改为前置
( y=--x;),程序运行结果会如何?
3.说明
( 1) 自增,自减运算,常用于循环语句中,使循环控制变量加 ( 或减 ) 1,以及指针变量中,使指针指向下 ( 或上 ) 一个地址 。
( 2) 自增,自减运算符,不能用于常量和表达式 。
例如,5++,--(a+b)等都是非法的 。
( 3) ++,--的结合方向是自右至左 。
( 4) 在表达式中,连续使同一变量进行自增或自减运算时,
很容易出错,所以最好避免这种用法 。 如,Print(―%d,%d‖,i,i++);
最好写成 j=i++;
Printf(―%d,%d‖,j,i);
3.8.2 逗号运算 (,) 及其表达式
C语言提供一种用逗号运算符,,,连接起来的式子,称为逗号表达式 。 逗号运算符又称顺序求值运算符 。
1.一般形式表达式1,表达式2,……,表达式 n
2.求解过程自左至右,依次计算各表达式的值,,表达式 n‖ 的值即为整个逗号表达式的值 。
例如,逗号表达式,a = 3 * 5,a * 4‖的值 =60:先求解
a = 3 * 5,得 a=15;再求 a * 4 = 60,所以逗号表达式的值
=60。
又例如,逗号表达式,(a = 3 * 5,a * 4),a + 5‖的值
=20:先求解 a = 3 * 5,得 a=15;再求 a * 4=60;最后求解
a + 5=20,所以逗号表达式的值 =20。
注意,并不是任何地方出现的逗号,都是逗号运算符 。 很多情况下,逗号仅用作分隔符 。
[Return]
总结:
1,C语言的数据类型?整型、实型、字符型、字符串型(其无变量)。
注:各数据类型的值域及在内存的存储形式。
2,赋值语句和赋值表达式
3,算术运算符和算术表达式( +,-,*,/,
++,--)
注:其优先级别及结合性。
4,逗号运算符和逗号运算表达式(表达式
1,表达式 2,…… 表达式 n )
作业:
P66
3.5,3.6,3.7,3.8,3.9、
3.10、
阅读程序:
1、写出程序的运行结果。
#include<stdio.h>
Main()
{short int a=32767,b;
b=a+1;
Printf(―a=%d,b=%d\n‖,a,b);
}
结果,a=32767,b= -32768
b的补码 =a的补码 +1 a的补码 =01111111 11111111
b的补码 =a的补码 +1=10000000 00000000
B的原值 =-( 11111111 11111111+1) = -( 10000000
00000000) = - 32768。
本题考查的是整数的内存存储方式。
2、写出下列程序的功能。
# include<stdio.h>
main()
{double d;
printf("输入一个 double数,");
scanf("%lf",&d);
d=d*100;
d=d+0.5;
d=(int)d;
d=d/100;
printf("保留两位小数,%g\n",d);
}
输入一个 double类型的数,使该数保留小数点后两位,对第 3位小数进行四舍五入运算。
3、写出下列程序的功能
#include<stdio.h>
main()
{int n,b1,b2,b3,b4;
printf("输入一个小于 10000的正整数,");
scanf("%d",&n);
b1=n%10;
n=n/10;
b2=n%10;
n=n/10;
b3=n%10;
n=n/10;
b4=n%10;
printf("各位上的数字分别为,%d %d %d %d\n",b4,b3,b2,b1);
}
输入一个小于 10000的正整数,求各位上的数字
4、写出下列程序的功能
#include<stdio.h>
main()
{char c1='c',c2='h',c3='i',c4='n',c5='a';
c1+=4;
c2+=4;
c3+=4;
c4+=4;
c5+=4;
printf("密码是 %c%c%c%c%c",c1,c2,c3,c4,c5);
}
将 China译成密码 Glmre
5、分析程序的运行结果:
#include<stdio.h>
#include<math.h>
main()
{char c1='a';
int a=1;
int c;
c=c1+a;
printf("%c\n",c1);
printf("%d\n",a);
printf("%d",c);
}
a
1
98
6、该程序的功能是首先定义一个整形变量,然后对其进行赋值,输出该变量:作自加和自减的操作,并将其输出。根据程序功能填空,并分析程序运行结果。
#include<stdio.h>
main()
{int a;
_____________;
printf("%d",a);
a++;
printf("%a",a);
--a;
______________;
}
1,a=10; 2,printf("%d",a); 结果,10%a1010