高级语言程序设计
第三章 数据类型、运算符与表达式
一,C语言的数据类型
3.1 C语言的数据类型 P38
? 基本类型
字符型 ( char) 1字节
整型 — 短整型( short int ) 2字节
基本型( int) 2字节 (-32768~ 32767)
长整型( long int ) 4字节( 〒 21亿 )
实型 — 单精度( float) 4字节 6~ 7位有效数字
长单精度( long float) 8字节 15~ 16位有效数字
双精度( double) 8字节 15~ 16位有效数字
长双精度( long double) 10字节 20位有效数字
可知对不同数据类型占用的存储空间,
char<short<=int<long <=float<double
求某一类型数据所占存储字节数,可用运算符,
sizeof(类型关键字)
Example:
main( )
{
printf(“char:%d字节 \n”,sizeof(char));
printf(“float:%d字节 \n”,sizeof(float));
}
结果显示,char:1字节
float:4字节
Let’s try…
3.2 常量与变量
3.2.1常量和符号常量
常量,在程序运行中,其值不能改变的量
常量的类型,
整型常量, 如 12,0,-4
实型常量, 如 2.3,-12.6
字符常量, 如 ‘ a?,?b?,?c?
字符串常量, 如, abc”,“I?am a teacher!”
符号常量, 用一个标识符代表一个常量
3.2.2 变量 P39
1,标识符 P40
2,C语言规则,标识符只能由字母,数字和下划线组成,
且第一个字母必须是字母或下划线,
3,标识符的长度,小于等于 32个字符
4,变量必须先定义后使用
5,变量名必须符合标识符命名规则
6,int a,b; a%b; (%表示求余,%必须要求两个数都
为整数 )
7,变量的类型,整形变量,实型变量,字符变量 (C语言
中无字符串变量 )
十进制整数 12 700000
八进制整数 以数字 0开头的数 012 -012
十六进制整数 以 0x开头的数 0x12 -0x12
3.3.2 整型变量
1.数据在内存中是以二进制的形式存放的,
例如,10的二进制形式为 1010,因为整型变量在内存中
占两个字节,所以 10在内存中的存储情况为
3.3 整型数据 P41
3.3.1.整型常量的表示方法
00000000 00001010
注意事项
? 数据存储形式
字符型按 ASCII码存储,其余以补码存储
示意图
字符型 (字符 'a')
用一个字节存放该字符的 ASCII值 (ASCII值表见 P374)
整 型 (十进制数 25037)
用两个字节存放该数值的补码
注,第一位均为符号位
01100001
01100001 11001101
? 对于 int a=8,b=-8;
0 0000000 00001000
符号位:
0—正数 1—负数
1 0000000 00001000
1 1111111 11110111
正数的原码 =正数的补码
负数的原码和补码按以下规则相互转换:
符号位不变,数值位各位取反,末位加 1。
0 0000000 00001000
原码
补码
符号位 数值位
a=810=10002 b=- 810=-10002真值
111000
2.整型变量的分类 P42
3.整型数据的溢出
? 整型 ≠整数
int 的范围,- 32768~+ 32767
Example:
#include <stdio.h>
#include <conio.h>
main()
{
int a ;
printf(“Input,”);
scanf(“%d”,&a);
printf(“a=%d\n”,a);
}
运行结果,
Input:12345
a=12345
Input:1234567
a= -10617
Why
!
Because,12345的补码是 0011000000111001
1234567的补码是 100101101011010000111
截去多余部份 (超过 2个字节的左边部分 )后
其原码为 1010100101111001(-10617)
参见教材 P44“整型数据的溢出”。
3.4 实型数据
?3.4.1实型常量的表示方法 P45
1,实数又称浮点数,有两种表示形式
十进制小数形式 它由数字和小数点组成 123.45
2.0 0.0 ( 必有小数点 )
指数形式 1.26e3 (1.26E3) 123e-4(123E-4)
注意,字母 e/E之前必须有数字,且 e/E后面的必须为整数
找错, e3,2.1e3.5
2.一个实数可以有多种指数的表示形式,例如
123e0,12.3e1,1.23e2,0.123e3
把其中 1.23e2称为“规范化的指数形式”,即在字母 e/E之前的
小数部分中,小数点左边应有一位 (且只能有一位 )非零数字,
实型常量本身无单或双精度
3.4.2 实型变量 P46
1.实型数据在内存中的存放形式
2.实型变量的分类
? 单精度 (float)型 6~7位有效数字
? 双精度 (double)型 15~16位有效数字
? 长双精度 (long double)型
3.5.1字符常量 P48
字符常量是用单撇号括起来的一个字符,
1,普通字符 (可显示字符)
‘ a?,?D?,?$?,???,?!? (只能单字符单引号)
2,转义字符 如‘ \n?
在程序中这些符号用表 3.3所示的“转义字符”表示。
因为 C语言区分大小写,所以‘ a?与‘ A?是不同的字符常量,
错误,‘ ABC?,A” ??? ?”? ?\?
3.5 字符型数据
转义字符例题分析
Example:
main(){
char ch;
ch=?\362?;
printf(“%c,%d”,ch,ch);
}
运行结果, ≥,- 14
ch = 3628=24210=111100102
111100102 化为原码为 10001110= - 1410
Exa ple:
#include <string.h>
main(){
printf(,a\n\”\x41\n”);
printf(“%d\n”,strlen(“a\n\”\x41”));
}
运行结果, a
“A
4
注,strlen为求字符串字节数函数(不计结束标志‘ \0?)。
Example,P49例 3.5
main(){
printf(“_ _ a b _ c \ t _ d e \ r f \ t g \ n,);
printf(,h \ t I \ b \ b j _ _ _ k” );
}
运行结果, _ _ a b _ c _ _ _ d e f _f _ _ _ _ _ _ _ g d e
h _ _ _ _ _ _ _ lj _ _ _ k
8列 8列8列
“\r”使当前
位置回到本
行开头,自此
输出的字符
(包括空格和
跳格所经过
的位置 )将取
代原来屏幕
上显示的字
符,
什么时候要使用转义字符?
转义字符只在特殊情况下才使用,
? C程序中需要实现某些特写打印或显示动作时
如 printf(“123\t56\n”);
? C程序中需要打印或显示以下三个字符时
\ (斜杠 ) " (双引号 ) ' (单引号 )
如 printf(“You?re a \”a bad egg!\”, );
? C程序中需要打印或显示 ASCII表中非键盘字
符时
如 printf(,Look \16 and \x80 !”);
3.5.2字符变量
一个字符变量在内存中占一个字
字符的存储 (P50):是将字符的 ASCII码存放到存储单元中
而不是把该字符本身放到存储单元中,
例如,?a? 的 ASCII码,97,在内存中的存储
那么字符的存储形式与整数的存储形式相似,这样使字符
数据和整型数据之间可以通用,
例如,?a? 若以 %d的形式输出 ---97
若以 %c的形式输出 ---a
01100001
? 整型和字符型均可为 unsigned (无符号型) P43图 3.4
此时 int 的范围 0~ 65535 char 的范围 0 ~ 255
Let’s try…
main() {
char c1,c2;
c1=?a?;c2=?b?;
c1=c1-32; c2=c2-32;
printf(“%c,%c\n”,c1,c2);
printf(“%d,%d\n”,c1,c2);
}
注意事项
? 在 C程序中,字符型可与整型 (≤255 )互相通用 P50-51
输出结果, a,b
97,98 输出结果, A,B
Example,
(参见 P50例 3.6,ACII值见 P374)
main() {
char c1,c2;
c1=97;c2=98;
printf(“%c,%c\n”,c1,c2);
printf(“%d,%d\n”,c1,c2);
}
思 考
?如果将例中 char改成
int,结果如何?
?如果将 c1=97改为
c1=97+3,结果如何?
? ‘A ’ 与, A, 的区别
?, China”占几个字节? ‘ \141’占几个字
节?
字符串常量是由一对双引号括起来的字符序列
,abc”,“I?am a teacher!”,“A”,“?”
?A?是字符常量,“A”是字符串常量,二者区别?P52
(以‘ \0?为字符串结束标志 )
? 字符串常量 P52
A A \0
?注意:用 char定义的字符变量只能接受字符常量,
而不能接受字符串常量( C语言中无字符串变量)
char a=?U? ; char b=“U”; (b被置为某随
机值)
? 问题(判断正误):
char c=“China”;
char c=?China?;
Example:
main() {
char c1=?a?,c2;
c2=98; printf(“%d,%d\n”,c1,c2);
}
结果:
97,98
Example:
main() {
char c1=“a”,c2;
c2=98; printf(“%d,%d\n”,c1,c2);
}
结果:
-108,98
若让 c1分别等于, U”、
,ABC”,,A”… 结果
不变
随机值
?符号常量
例 /*给定半径,求圆的面积 */
#define PI 3.14159
#include <stdio.h>
#include <math.h>
main( ) /*主函数 */
{
float r,s;
r =1.0; /*变量 r赋初值 */
s=PI * pow(r,2); /*计算圆面积 s*/
printf (“R=%f, S=%f \n”,r,s);
用一个标识符代表一个常
量的称为符号常量,
与变量的区别,符号常量
的值在其作用域内不能改
变,也不能再被赋值,
注意,符号常量名用大写,
变量名用小写已示区别,
注意不得与关键字同名,
因为 C语言区分大小写,大
小写为不同字符,
3.6 变量赋初值
? 变量定义
一般格式:变量类型名 变量名 1,…,变量名 N;
例,int x,y;
? 赋初值 P53
1,int a; a=3;相当于 int a=3;
float f; f=3.14; 相当于 flaot f=3.14;
char c; c=?a?; 相当于 char c=?a?;
2,也可使定义的变量的部分赋初值
如, int a,b,c=5; 相当于 int a,b,c; c=5;
3,如果对几个变量赋初值 3.应该写成
int a=3,b=3,c=3;
而 int a=b=c=3;是错误的,
定义变量
的同时使
变量初始

?赋值
例,int a=b=c=d=3+5
(语法错误,除非 b,c,d定义过)
正确,int a,b=a=3+5;
例,b=(a=3+5) a=b=c=d=3+5
(结果均为 8)
例,c=3+(a=5)*6
结果,c=33,a=5(一个语句可以有几个赋值运算)
3.7数据间的转换(混合运算)
? 数据的类型级别 P54图 3.10
? 基本规则
?不同类型运算量参加运算,遵守“向高看齐”的类型
一致化规则:将长度较短的运算量转换为长度较长的
运算量,以保证不丢失信息。
?将实型常量赋给整型变量,将被自动取整
int a=7.999999 ; 等效于 int a=7;
?float型只要参加运算,均自动转为 double。
main()
{
float i=3,j=4;
printf(“%d\n”,sizeof(i) );
printf(“%d\n”,sizeof(i/j) );
} /*结果为 8(双精度) */
3.8算术运算符和算术表达式
C语言运算符( 13类) P55
1,基本的算术运算
+ - * / %(模运算符 /求余运算符 )
例,14%(-4)=-2 -14%(-4)=2
? %两侧均为整型数据, 例,20.4%2(出错 )
? 两个整型数相除,其值也一定是整型数(取商之整数部
分)。 例, 3/2的值为 1而非 1.5 (1/2=?)
2,运算符的优先级与结合性 P375
运算规则,先按优先级,若优先级相同,按规定的结合方向处理
例, 2.5+7%3*7%2/4的值是什么?
2.500000 (1/4为 0)
例, float x,y; x%y; (出错 )
3,强制类型转换 P56
强制类型转换运算符可以将一个表达式转换成所需类型
一般形式, (类型名 )(表达式 )
例 ;(float)(5%3) 将 5%3的值转换成 float型
1,强制类型转换时,类型符用 ()括上,(int)a%2
类型转换运算符的优先级大于求余的优先级 P375
所以 (int)a%2 先对 a取整再求余
2,表达式用括号括起来,
例, (int)x+y 是先将 x取整再与 y相加
(int) (x+y) 是先将 x与 y相加再取整
3,转换后表达式的数据类型为新的类型,但表达式中变
量本身类型不变。
main()
{ int x=5; float y=3.5;
clrscr(); /*clear screen(清屏 )*/
printf(“%d”,(int)y+x);
} 结果是什么?
程序执行后 y
的类型是什么?
8
4,int 型强制转换成 float/double型 -----小数点后填 0
float/double 型强制转换成 int型 -----小数点后数字全部抹去
例,( int)3.5 的值是多少?
例:若 int a=7;float x=2.5,y=4.7; 则表达式
x+a%3*(int)(x+y)%2/4 的值是什么? 2.5
3
3.5
main()
{ int x; float y=3.6;
x=(int)y; printf(“y=%f,x=%d”,y,x);
} 结果是什么?
结果, y=3.6000000,x=3
y仍为 float型,未发生变化
x为什么等
于 3?
例:若 int a=2,b=3;float x=3.5,y=2.5; 则表达式
(float)(a+b)/2 +(int)x%(int)y 的值是什么?
++(自加运算符) --(自减运算符)
用法, +1 -1 运算
a、前缀形式 (在使用 i之前,先使 i的值加 /减 1)
int i=5; x = ++ i ; y= i ; (x=6,i =6,y=6)
int i =5; ++ i ; y= i ; ( i =6,y=6)
b、后缀形式 (在使用 i之后,使 i的值加 /减 1)
int i =5; x = i ++; y= i ; (x=5,i =6,y=6)
int i =5; i ++; y= i ; ( i =6,y=6)
若对某变量自加 /自减而不赋值,结果都是使该变量自身 ± 1;
若某变量自加 /自减的同时还要参加其他运算,则前缀运算是先
变化后运算,后缀运算是先运算后变化。
注意,运算对象只能是整型变量,5++或 (x+y)++均为错
4,自加、自减运算符 P57
++和 - - 的结合方向是“自右至左”
例, int i=3;
printf(“%d”,-i++);
因为符号运算符和,++”运算符同优先级,而结合方向是自
右至左的,所以 -i++相当于 -(i++).所以输出结果为 -3,i增值为
4
例一:
main()
{
int a=10;
printf(“%d\n”,a);
printf(“%d\n”,++a);
printf(“%d\n”,a++);
printf(“%d\n”,a);
} 运算结果,10 11 11 12
例二:
若 int x=3,y; 求下列运算后 y和 x的值
y=x++ -1; (2 4)
y=++x -1; (3 4)
y=x - - +1; (4 2)
分析思路:先对右边的表达式进行扫描,如果 x++,先取 x值
完成表达式运算后再让 x自加 1,如果 ++x,则先将 x自加 1后再
代入表达式进行其他运算
例三:
若 int i=3 求下列运算后 y和 z的值
y=(i++)+ (i++)+ (i++); y=9 (3+3+3)
z=(++i )+ (++i )+ (++i ); z=18 (6+6+6)
分析思路:先对右边的表达式进行扫描,看是否需要先自加,
如需要,就作若干次自加,然后再进行表达式的其他运算。
思考:
y=(++ i)+ (i++)+ (++ i); y=15 ( 5+5+5)
3.9、赋值运算符和赋值表达式
1,赋值符号,=”就是赋值运算符,作用,将一个数据
付给一个变量,
2,复合的赋值运算符 P62
+= -= *= /= %= 等
a+=3等价于 a=a+3 x*=y+8等价于 x=x*(y+8)
c/=3等价于 c=c/3 x%=3等价于 x=x%3
例,c=b*=a+3
相当于 (1)a+3 (2)b=b*(a+3) (3)c=b
例:若 i, j 的初值分别为 3和 4,则执行 j+=i- =1
后 i, j 的值为多少? 解题步骤:
i=i-1=3-1=2
j=j+i=4+2=6
结果,i=2,j=6
? 关于优先级和结合方向:
C语言规定了运算符的优先级和结合性。在表达式求值时,
先按运算符的优先级别高低次序执行。如果在一个运算对
象两侧的运算符的优先级别相同,则按规定的结合方向处
理。
(各种运算符的优先级和结合性见 P375附录 Ⅲ )
【 例 】 设 i,j初值分别为 3和 4,则执行 j+=i-=1;后
i,j的值为多少?
【 例 】 若 x=7;则 x+=x-=x+x的值是多少?
( i=2,j=6)
( -14)
解法:从右到左,先做 x=x-(x+x)=-7,
再做 x=x+x=-14
3.10逗号运算运算符和逗号表达式 P63-64
C语言中逗号可作分隔符使用,将若干变量隔开
如 int a,b,c;
又可作运算符使用,将若干独立的表达式隔开,并
依次计算各表达式的值。其一般形式
表达式 1,表达式 2,…, 表达式 n;
逗号表达式的求解过程:先求表达式 1的值,再求
表达式 2的值 …,最后求表达式 n的值。整个逗号表
达式的值是最后一个表达式 n的值。
在 C语言所有运算符中,逗号表达式的优先级最低。
【 例一 】
main( )
{
int x,a;
x=(a=3*5,a*4,a+5);
printf(“x=%d,a=%d\n”,x,a);
}
【 例二 】
main( )
{
int x,a;
x=(a=3*5,a*4),a+5;
printf(“x=%d,a=%d\n”,x,a);
}
运算结果,x=20,a=15 运算结果,x=60,a=15
【 例三 】 main()
{ int a,b,x;
x=(a=8,b=15,b++,a+b);
printf(“a=%d,b=%d,x=%d\n”,a,b,x);}
运算结果,a=8,b=16,x=24
1,关系运算(比较运算) P87
关系运算符,> < >= <= == !=
关系表达式,含有关系运算符的表达式
特别注意 a≤X≤b 之类算式的正确写法, a<=x
&& x<=b(错误写法,a<=X<=b)
【 注意 】 关系表达式的值,真 —1 假 —0;
C语言中还规定,非 0—真 0—假
优先级,算术 >关系 >赋值 >逗号
运算符的补充
【 例一 】
main( )
{
int m=5;
if (m++>5)
printf(“m>5”);
else
{
printf(“m=%d,”,m--);
printf(“m=%d”,m--);
}
}
运算结果,m=6,m=5
【 例二 】
main( )
{
int m=5;
if (++m>5)
printf(“m>5”);
else
{
printf(“m=%d,”,m--);
printf(“m=%d”,m--);
}
}
运算结果,m>5
2,逻辑运算符和逻辑表达式 P88
逻辑运算符:
&&(与运算符) 运算符两边均为真时,结果为真
||(或运算符) 运算符两边均为假时,结果为假
! (非运算符) 将运算符右边真假倒置
逻辑运算符的任一端如果为非 0数,则视为“真”,为 0则视
为假。
【 例 】 printf(“%d”,!3+5) 结果为 5
printf(“%d”,!0+5) 结果为 6
注意,! 优先于关系运算符,与 ++,--同级。
常用优先级:
!,++,-- >算术运算符 >关系运算符 >&& >|| >赋值 >逗号
【 例一 】
main( )
{
int a=1,b=2,m=2,n=2;
(m=a>b)&&++n;
printf("%d\n",n);
}
【 例二 】
main( )
{
int a=1,b=2,m=2,n=2;
(m=b>a)&&++n;
printf("%d\n",n);
}
运行结果,n=2 运行结果,n=3
原因:
在 &&和 ||的左边如果能判断出结果,则右边不再作运算。
结论,在逻辑表达式的求解中,并不是所有的逻辑运算符都会被
执行。只是在必须执行下一个逻辑运算符才能求出表达式的解时,
才执行该运算符。 ( P90)
【 例三 】
有以下程序段:
int a,b,c;
a=b=c=1;
++a||++b&&++c;
问执行后 a,b,c的值各是多少?
a=2,b=1,c=1
【 例四 】 编程判断任一给定年份是否闰年。符合以下条件的
年份为闰年,P91
① 能被 4整除但不能被 100整除;
②能被 4整除又能被 400整除(只需考虑能被 400整除的情况)
main()
{ int year;
clrscr();
printf("Input year=");
scanf("%d",&year);
if ((year%4==0&&year%100!=0)||year%400==0)
printf("\n%d is a leap year!",year);
else
printf("\n%d isn't a leap year!",year);
}
3,条件运算 P96
条件运算符:
…?…, … (三元运算符,即需连接三个运算量)
一般形式,e1?e2:e3
( e1为条件表达式,e2,e3为任意类型表达式)
功能:
如果 e1≠0(为真),运算结果为 e2的值。
如果 e1=0(为假),则取 e3的值。
例如,int x=3,y=2;
printf(“%d”,x<y?y:x);【 例 】 分别令 x=3,x=0,x= -5,求运行结果。本程序功能?main( )
{ int x,y;
printf(“Input x=”);
scanf(“%d”,&x);
y=x>0?1:x<0?-1:0; /*结合方向:由右向左 */
printf(“x=%d,y=%d\n”,x,y);
}
结果:
x=3,y=1
x=0,y=0
x=-5,y=-1
1 (x>0)
y= 0 (x=0)
-1 (x<0)
4,sizeof运算符
sizeof运算符是一个单目运算符,用以计算
操作数在内存中占用的字节数。它的操作数
可以是以下两种情况:
● 类型标识符;
● 一个表达式 main(){
int a=4,b;
b=a+sizeof(double)+sizeof(a+2.14);
printf("b=%d\n",b);
}
结果,b=20
5,C程序中的算术表达式
【 例 】 编程求以下数学表达式的值(设 x=15)
#include <math.h>
main( )
{
int x=15;
double y;
y=sqrt(pow(sin(15*3.14/180),2.5))/8/log10(2*3.14)
+fabs(exp(2.5)-x);
printf("y=%f",y);
}
作业
一、编程题
已知 x=15,编程求:
要求输出结果以指数形式表示。
xlo gx ln x85)s in ( 4 5 10????
xlo gx ln x85)s in ( 4 5 10????
xlo gx ln x85)s in ( 4 5 10????
1、填空
① C程序都是从 函数开始执行。
② C程序的语句都是用 结束。
③ 用来在屏幕上显示信息的库函数是 。
④ 用来从键盘读取数据的库函数是 。
⑤ C程序中 用来提高程序的可读性。
⑥ 若 x和 n均是 int型变量,且 x和 n的初值均为 5,则计算表达式
x+ =n++后,x的值为, n的值为 。
⑦ 若有定义,int b=7; float a=2.5,c=4.7;则以下表达式的值
为 。 a+(int)(b/3*(int)(a+c)/2)%4
⑧ 若 a是 int型变量,且 a=6,则计算表达式 a+=a-=a*a后,a的值
为 。
⑨ 假设所有变量均为整型,则表达式 (a=2,b=5,a++,b++,a+b)的
值为 。
⑩ 判断 char型变量 c1是否为小写字母的正确表达式是 。
A) 'a'<=c1<='z' B) (c1>=a)&&(c1<=z)
C) ('a'>=c1)||('z'<=c1) D) (c1>='a')&&(c1<='z')
2、教材,P66 第 3.9题 P104 第 5.3题