第 2章 C语言基础北京科技大学 计算机系
C 语言程序设计
2009-8-17
2本章主要内容
本章介绍 C语言的基础,包括:
– 数据类型
– 运算符和表达式
均是程序设计的基本知识
为什么讨论 这些知识?
通常 程序 要对数据进行操作处理:
– 处理的对象是 数据
– 通过 运算符和表达式 进行操作
2009-8-17
3例如:
【 例 2.1】 计算圆的面积,半径为 5 cm。
程序如下:
main( )
{ float r,area ;
r=5 ;
area=3.14*r*r;
printf ("%f\n ",area) ;
}
运算结果是输出 圆的面积,78.500000
程序中用到的数据,r,area,5,3.14
对数据进行的运算,*,=
例 jc2_1
2009-8-17
4分析:
计算机操作处理时,要完成以下工作,
在内存中给半径 r 和运算结果 area 开辟存储空间,存放它们的值。 应该留多大的地方来存放它们的值?
数据 5 和 3.14 与 r,area 不同,它们是在编写程序时就给出确定的值,在运算过程中不会改变。 这样的数计算机怎么处理?
对 整数 5 和 小数 3.14,计算机 存放时是否有区别?
涉及数据类型的基本知识
2009-8-17
5C语言的数据类型
C数据类型 数组类型结构体类型共用体类型枚举类型整型字符型实型 (浮点型 )
空类型单精度型双精度型基本类型指针类型构造类型本章讨论基本类型数据
2009-8-17
62.1.1 整型数据
1,整型数据的类型
– 基本整型数据 int,分配 2 Byte
– 短整型数据 short int,分配 2 Byte
– 长整型数据 long int,分配 4 Byte
整型数据均以 二进制补码 形式存储问题:
为什么要采用补码?
如何表示?
2009-8-17
7计算机中正,负数的表示例如,109 = (1101101)2
要区别:+ 109 和 - 109
方法是,将符号也数码化即,正的符号 + 用 0 表示负的符号 - 用 1 表示
∴ 计算机中的数表示方法是:
符号位 + 二进制数值 (以 8bit 为例 )
+ 109 → + 110 1101 → 0110 1101
- 109 → - 110 1101 → 1110 1101
2009-8-17
8问题:计算机计算复杂化例如计算,( -19) +( +22)
1001 0011 + 0001 0110
解决的方法是:
使用 反码 或 补码 的表示方法(按前述表示的编码称为 原码 ),即能将减法一律转换为加法。
需要判断符号是否相同:
如果相同,结果符号不变,并进行绝对值相加
如果不同,结果取绝对值大的数的符号,并进行绝对值相减
2009-8-17
9原码、反码和补码
正数,原码、反码、补码相同
– 符号位为 0,数值为对应的二进制数。
+ 109
[01101101]原 = [01101101]反 = [01101101]补
负数,
– 原码 符号位为 1,数值为绝对值的二进制数。 - 109 [11101101]原
– 反码 符号位为 1,数值为绝对值的二进制数各位变反。 - 109 [10010010]反
– 补码 符号位为 1,数值为绝对值的二进制数各位变反加 1。 - 109 [10010011]补
2009-8-17
102,有符号和无符号整型数据
– 有符号的整型数据 signed int
– 无符号的整型数据 unsigned int
区别是将 最高位 看作符号位还是数据位例如,1111 1111 1010 1000
作为 有符号数 使用时,最高为符号位为负数,值是,- 88(再求一次补)
作为 无符号数 使用时,最高为数据位为无符号的数,值是,65448
2009-8-17
11例如:
main( )
{ unsigned int m;
m= 65448;
printf("\nm=%d\n",m);
printf("m=%u\n",m);
}
例
jc2_a
输出结果:
m=-88
m=65448
按有符号数输出按无符号数输出
2009-8-17
12整型数据的类型及规定
方括号表示可选项
int 分配 2 Byte,long分配 4 Byte
类型名称 类型符 bit 取值范围整型
(短整型 )
[signed] int
[signed] short [int]
16 -215~ 215-1
(-32768~ 32767 )
无符号整型 unsigned [int] 16 0 ~ 2
16-1
(0~ 65535 )
长整型 [signed] long [int] 32 -231~ 231- 1
无符号长整型 unsigned long [int] 32 0 ~ 232-1
2009-8-17
132.1.2 实型数据
1.实型数据的类型
– 单精度实型数据 float,分配 4 Byte
– 双精度实型数据 double,分配 8 Byte
2.实型数据的存储单精度实型指数部分小数部分小数的符号位 指数的符号位
2009-8-17
14实型数据的类型及规定
C标准并未具体规定各种实型数据所占字节数,也不规定具体小数和指数部分的位数。
一般而言,小数部分位数多,数据表示的有效数字多,
精度就高;而指数部分位数多,则表示的数据范围更大。
有效数字的意义?
类型 类型符 Byte 绝对值的范围 有效数字单精度型 float 4 10-37 ~ 1038 7~ 8 位双精度型 double 8 10-307 ~10308 15~ 16位例 jC2_a
2009-8-17
152.1.3 字符型数据
字符型数据 char,分配 1 Byte
字符型数据是指字母、数字、各种符号等用 ASCII值表示的字符
例如 'a' 是一个 char类型数据,称作字符常量,存储:
0 1 1 0 0 0 0 1
2.1.4 空类型
空类型 void
通常与指针或函数结合使用
2009-8-17
162.2 常量、变量与标准函数
主要内容:
– 常量
– 变量
– 标准库函数
2009-8-17
172.2.1 常量
在运行程序的过程中值保持不变的量
1.整型常量
– 十进制,0~9
– 八进制,0~7,以 0开头
– 十六进制,0~9,A~F/a~f,以 0x或 0X 开头例如:
100 -8 0 +123
010 024 0100 073
0x38 0x10 0X10 0XFF 0x0a
2009-8-17
181,整型常量
整型常量的类型:
– 根据值大小默认类型。
– 整型常量后面加 l或 L,则认为是 long int型例如,123L,0L,432l,0x100l
注意:
十六进制常量中可以使用大写字母 A~ F,
也可以使用小写字母 a~ f。
八进制常量中不能出现数字 8 或 9
例如,018,0921非法
2009-8-17
192,实型常量
– 十进制形式
1.0 1,+12.0 -12.0 0.0
– 指数形式
1e3 1.8e-3 -123E-6 -.1E-3
等价于,1× 103 1.8× 10-3 -123× 10-6 -0.1× 10-3
指数只能是整数,而尾数则可以是整数也可以是小数,无论指数或尾数均不能省略例如,1e,E.5,E-3 非法
实型常量的类型:默认为 double型,后面加 F
( 或 f),则强调表示该数是 float类型例如,3.5f,1e2F
2009-8-17
203,字符型常量
可视字符常量
– 单引号括起来的单个可视字符例如,'a','A','+','3',' ' 等
转义字符常量
– 单引号括起来的 \与 可视字符 组合,例如:
\0 字符串结束标志
\n 回车换行
\t 跳到下一个输出位置
\" 双引号字符
\ddd ddd为 1到 3位八进制数所代表的字符
\xhh hh为 1到 2位十六进制数所代表的字符
2009-8-17
214,字符串常量
用双引号括起的一个字符序列
– 例如,"ABC","123","a","\n\t "
"\nGood morning"
字符串常量的长度,
– 所包含的字符个数
字符串常量的存储方式:
\n G o o d m o r n i n g \0
a \0
所占存储单元数,串长度+ 1
例如:
字符串结束标记
2009-8-17
225,符号常量
以标识符来代表的常量
事先编译预处理命令 define定义
编译时先由系统替换为它所代表的常量,再进行编译例如:
#define LEN 2.5
main( )
{ float a,b;
a= 2*3.14 *LEN;
b=3.14*LEN*LEN;
printf("a=%f,b=%f\n",a,b);
}
定义符号常量使用符号常量编译前系统进行替换
2009-8-17
235,符号常量
main( )
{ float a,b;
a= 2*3.14 *2.5;
b=3.14*2.5*2.5;
printf("a=%f,b=%f\n",a,b);
}
define是编译预处理命令,必须以,#”开头
编译预处理命令在第 7章讨论。
替换为
2009-8-17
242.2.2 变量
1,变量的有关概念
在程序运行过程中,其值改变的数据,称为变量,变量用标识符表示,称为 变量名 。
变量必须“先定义后使用”
系统为变量分配存储单元,存储变量的值。
编写程序时通过变量名来存、取 变量值 。
a
510 变量值为变量分配的存储单元变量名例如:
有 变量 a
它的值是 510
2009-8-17
252,变量定义变量定义的一般格式:
数据类型说明符 变量列表 ;
例如,int i,j;
long k,m;
float x,y;
char ch1,ch2;
必须使用合法的标识符作变量名
不能使用关键字为变量命名
2009-8-17
263,变量的初始化:
允许在说明变量的时候对变量赋初值。
例如,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;
2009-8-17
272.2.3 标准库函数
由 C编译系统定义的一种函数,存放在系统函数库中,用户可以根据需要随时调用
常用函数如,printf,scanf,fabs,sqrt,sin、
(常用数学函数参见教材 P30表 2.5 )
函数调用形式,
函数名([参数表])
例如,putchar('a')
sqrt(x) 例 jc2_3
2009-8-17
282.3 运算符和表达式
主要内容:
– 算术运算符和算术表达式
– 赋值运算符和赋值表达式
– 关系运算符和关系表达式
– 逻辑运算符和逻辑表达式
– 位运算符和位运算表达式
– 条件运算符和条件表达式
– 逗号运算符和逗号表达式
– 其他运算符及其运算
2009-8-17
29运算符的有关概念
作用:
– 对运算对象完成规定的操作运算
类型:
– 按运算对象分:
单目、双目、三目
– 按功能分:
算术、赋值、关系、逻辑
条件、逗号、位、其他
2009-8-17
30运算符的优先级和结合性
优先级
– 指各种运算符号的运算优先顺序例如,算术运算优先于关系运算算术运算中先 * / 后 + -
结合性
– 指运算符号和运算对象的结合方向
– 分为:从左向右 (左结合 )和从右向左 (右结合 )
例如,算术运算符为 左结合 a-b+4
赋值运算符为 右结合 a= b = 5
( C语言规定见教材 P297 附录 B)
2009-8-17
31本章涉及的运算符
+ - * / % ++ -- + -
= += -= *= /= %=
&= |= ^= >>= <<=
> < >= <= == !=
&& || !
& | ^ ~ << >>
:
,
& sizeof (数据类型标识符 )
类型 种类算术运算符赋值运算符关系运算符逻辑运算符位运算符条件运算符逗号运算符其他运算符
2009-8-17
32表达式的有关概念
什么是表达式
– 由 运算符 将运算对象连接成的式子,它描述了一个具体的求值运算过程。
计算表达式的值
– 按照运算符的运算规则求值
– 求值时注意运算符的优先级和结合性
表达式值的类型
– 自动转换
– 强制转换
2009-8-17
33例如:
表达式:
150+'b'*2- 12.456
b=(++a)-2
a /= a *= (a = 2)
f=a>b>c
--a ||++b&&c++
max=a>b? a,b
a=3,a+=3,a*a
1/(float)a+6
2009-8-17
34算术运算
算术运算符的优先级
( ) + - ++ -- * / % + -
同级 同级 同级单目 双目高 低
没有乘方运算符,要计算 a3要写作 a*a*a 的连乘,
或用标准库函数 pow(a,3)
―/‖的运算对象可为各种类型数据,但是当进行两个整型数据相除时,运算结果也是整型数据
,%”要求运算对象必须是整型数据,功能是求两数相除的余数,余数的符号与被除数的符号相同。
2009-8-17
35自增自减运算
++ --是 单目运算符
有前缀和后缀 两种形式
– 前缀形式,先自增 (自减 )再引用;
– 后缀形式,先引用再自增 (自减 );
功能:
前缀形式 ++ a 等价于 a = a + 1
-- a 等价于 a = a – 1
后缀形式 a ++ 等价于 a = a + 1
a -- 等价于 a = a – 1
表达式的值会不同
2009-8-17
36例如:
当 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
2009-8-17
37说明:
++ 和 -- 的运算对象只能是变量(或运算结果是变量的表达式),不能是常量(或运算结果是数值的表达式)。
例如,5++,(a+2)++ 不合法。
具有右结合性,结合方向为从右到左。
例如,–a++ 等价于 -(a++)
如果有多个运算符连续出现时,C系统尽可能多的从左到右将字符组合成一个运算符例如,i +++ j 等价于 ( i++)+j
-i+++-j 等价于 -(i++)+(-j)
2009-8-17
38
main( )
{ int a=5;
printf("%d %d\n",a,a++ );
}
说明(续):
对函数参数的求值顺序:
– Turbo C系统先计算最右边的参数值,
再依次计算左面的参数值。
【例 2.5】有多个函数参数且为同一变量自增的运算处理。
输出结果:
6 5
运行例 2.5
2009-8-17
39说明 ( 续 ),
【例 2.6】有多个函数参数且为同一变量多次自增的运算处理。
main( )
{ int a=5;
printf("%d%d\n",a,(a++)+( a++));
}
输出结果:
7 11
运行例 2.6
2009-8-17
40赋值运算
赋值运算符 (右结合)
= += -= *= /= %=
&= |= ^= >>= <<=
赋值表达式
– 将 表达式的值 存入 变量 对应的内存单元中
m=12
b=(++a)-2
m%=3+n 等价于 m=m%(3+n)
x *= (x = 5)
2009-8-17
41说明:
赋值号左边必须是变量,右边可以是 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
2009-8-17
42关系运算
关系运算符 (左结合)
> >= < <= == !=
较高 较低
关系表达式
– 用关系运算符将运算对象连接成的式子例如,12< 'C'+1 ( 字符型数据比较 ASCII值)
a==b>=c 等价于 a == ( b>=c )
与 (a==b)>=c 不等价
关系运算符优先于赋值,低于算术
2009-8-17
43说明:
关系运算的结果应该是 逻辑值 。 C语言用数值用 1 表示 逻辑真,0 表示 逻辑假例如,7>5 的值是 1,5>7 的值是 0
'a'>'b'的值是 0,'a'<'b' 的值是 1
即关系表达式的值,0 或 1
实型数 可进行大于或小于比较,但通常不进行 == 或 != 的关系运算
2009-8-17
44逻辑运算符
逻辑运算符
&& || !
逻辑运算符的运算规则运算对象 逻辑运算结果
a b a&&b a || b !a
非 0 非 0 1 1 0
非 0 0 0 1 0
0 非 0 0 1 1
0 0 0 0 1
2009-8-17
45逻辑表达式
逻辑表达式
– 用逻辑运算符将运算对象连接成的式子例如,0&&'b'
a &&b || c&&d
a || b-5 || c/4
!x+y >= z
逻辑运算符的优先级 和结合性:
– !是单目运算符,右结合,高于算术
– && 和 || 是双目运算符,左结合,高于赋值运算符,低于关系运算符
2009-8-17
46逻辑运算规则
从左到右依次进行逻辑计算
– 运算对象为 非 0表示 逻辑真
– 运算对象为 0 表示 逻辑假
逻辑运算的结果为 0 或 1
例如设,a=15,b=0,c=-2
a && b && c 结果为 0
a || b || c 结果为 1
(a+c) || b && c 结果为 1
2009-8-17
47逻辑运算规则 ( 续 )
运算按照 从左至右 的顺序进行,一旦能够确定逻辑表达式的值,就立即结束运算
——逻辑运算的短路性质例如 设,a=1,b=0,c=-2
a && b && c
(a++) || ++ b&& --c
为 0,运算终止,表达式 值 为 0
为非 0,运算终止,表达式值为 1
且 a为 2,b为 0,c为 -2 (b,c保持原值 )
2009-8-17
48关系与逻辑运算符的应用
表示数学公式 a>b>c
判断 a,b,c三条线段能否组成一个三角形
a,b不同时为负
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)
a>b && b>c
2009-8-17
49位运算符
~ & ^ | << >>
位逻辑运算符 移位运算符单目
位运算符的运算对象只能是 整型数据 或字符型数据,不能是实型数据
运算对象一律按二进制补码参加运算,
并 按位进行运算
位运算的结果是一个整型数据低于单目、算术运算符,
高于其他运算符低于单目、算术和关系运算符,高于其他运算符
2009-8-17
50位逻辑运算符的运算规则
假设 ai和 bi均是一个二进制位( bit)
运算对象 逻辑运算结果
ai bi ai&bi ai|bi ai ^bi?ai
0 0 0 0 0 1
0 1 0 1 1 1
1 0 0 1 1 0
1 1 1 1 0 0
例如,假设 a=10,b=010
求 a&b,a | b,a^b,?a
2009-8-17
51程序如下:
main( )
{ int a=10,b=010;
printf("%d %d\n",a&b,a|b);
printf("%d %d\n",a^b,~a);
}
输出结果:
8 10
2 -11
0000 0000 0000 1010
& 0000 0000 0000 1000
0000 0000 0000 1000
即,a&b的值是 8
0000 0000 0000 1010
1111 1111 1111 0101
即,?a的值是 -11
运行 jc2_b
2009-8-17
52移位运算
例如:
a<<b
a+8>>b-1 等价于 (a+8)>>(b-1)
例如,假设 a=10,b=2,求 a<<b,a+8>>b-1
main( )
{ int a=10,b=2;
printf("%d %d\n",a<<b,a+8>>b-1);
}
输出结果:
40 9
运行 jc2_c
请自行分析运行结果
2009-8-17
53条件表达式运算
条件运算符,?,
条件表达式的一般形式表达式 1? 表达式 2,表达式 3
例如,m<n? x,a+3
a++>=10 && b-->20? a,b
x=3+a>5? 100,200
C语言中唯一的 三目运算符,要正确区分用? 和,分隔的表达式
涉及条件运算符的优先级与结合性
2009-8-17
54条件运算符优先级
条件运算符优先级高于赋值、逗号运算符,
低于其他运算符例如:
⑴ 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 )
2009-8-17
55条件运算符的结合性
条件运算符具有 右结合性
当一个表达式中出现多个条件运算符时,
应该将位于最右边的问号与离它最近的冒号 配对,并按这一原则正确区分各条件运算符的运算对象。
例如,w<x? x+w,x<y? x,y
与 w<x? x+w,( x<y? x,y) 等价与 (w<x? x+w,x<y)? x,y 不等价
2009-8-17
56逗号表达式运算
逗号表达式的一般形式表达式 1,表达式 2,……,表达式 n
逗号表达式的值
– 从左向右,依次对表达式求值,最后得到 表达式 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
2009-8-17
57取地址运算符 &
– 为单目运算符
– 运算对象只能是变量
– 运算结果是变量的存储地址例如有定义,
int a,student;
char ch;
可以对变量 a,ch,student 进行 &运算:
&a &ch &student
2009-8-17
58长度运算符 sizeof
– 为单目运算符
– 运算对象只能是 变量名 或 数据类型标识符
– 运算结果为该变量或该数据类型的长度
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));
}
输出结果:
2 2 8 8 4 1
运行 jc2_d
2009-8-17
592.4 运算中数据类型的转换
2.4.1 数据类型的自动转换
转换原则,自动将精度低、表示范围小的运算对象类型向精度高、表示范围大的运算对象类型转换
char,short
double
long
float
unsigned
int
高精度低精度例如有定义:
int a; char ch;
表达式:
a-ch*2+35L
a-ch*2+ 35.
2009-8-17
602,赋值运算中的类型转换
<实型变量 > = <整型表达式 >
– 小数部分自动补 0
<整型变量 > = <实型表达式 >
– 自动舍去实型表达式的小数部分( 注意不进行四舍五入 )
<字符变量 > = <整型表达式 >
<整型变量 > = <长整型表达式 >
– 自动截取表达式值的低字节赋值,舍去高字节
<整型变量 > = <字符数据 >
<长整型变量 > = <整型表达式 >
– 自动给高字节补 0 或 补 1
2009-8-17
612.4.2 数据类型的强制转换
强制转换的一般形式
(类型名 ) 表达式例如,(int)( 'b'+3*x)%3
1/(float)a+6
注意:
(float) 22/5 与 (float) (22/5) 不同
错误的类型转换:
(int) b=a+5
b= int (3*a)
C 语言程序设计
2009-8-17
2本章主要内容
本章介绍 C语言的基础,包括:
– 数据类型
– 运算符和表达式
均是程序设计的基本知识
为什么讨论 这些知识?
通常 程序 要对数据进行操作处理:
– 处理的对象是 数据
– 通过 运算符和表达式 进行操作
2009-8-17
3例如:
【 例 2.1】 计算圆的面积,半径为 5 cm。
程序如下:
main( )
{ float r,area ;
r=5 ;
area=3.14*r*r;
printf ("%f\n ",area) ;
}
运算结果是输出 圆的面积,78.500000
程序中用到的数据,r,area,5,3.14
对数据进行的运算,*,=
例 jc2_1
2009-8-17
4分析:
计算机操作处理时,要完成以下工作,
在内存中给半径 r 和运算结果 area 开辟存储空间,存放它们的值。 应该留多大的地方来存放它们的值?
数据 5 和 3.14 与 r,area 不同,它们是在编写程序时就给出确定的值,在运算过程中不会改变。 这样的数计算机怎么处理?
对 整数 5 和 小数 3.14,计算机 存放时是否有区别?
涉及数据类型的基本知识
2009-8-17
5C语言的数据类型
C数据类型 数组类型结构体类型共用体类型枚举类型整型字符型实型 (浮点型 )
空类型单精度型双精度型基本类型指针类型构造类型本章讨论基本类型数据
2009-8-17
62.1.1 整型数据
1,整型数据的类型
– 基本整型数据 int,分配 2 Byte
– 短整型数据 short int,分配 2 Byte
– 长整型数据 long int,分配 4 Byte
整型数据均以 二进制补码 形式存储问题:
为什么要采用补码?
如何表示?
2009-8-17
7计算机中正,负数的表示例如,109 = (1101101)2
要区别:+ 109 和 - 109
方法是,将符号也数码化即,正的符号 + 用 0 表示负的符号 - 用 1 表示
∴ 计算机中的数表示方法是:
符号位 + 二进制数值 (以 8bit 为例 )
+ 109 → + 110 1101 → 0110 1101
- 109 → - 110 1101 → 1110 1101
2009-8-17
8问题:计算机计算复杂化例如计算,( -19) +( +22)
1001 0011 + 0001 0110
解决的方法是:
使用 反码 或 补码 的表示方法(按前述表示的编码称为 原码 ),即能将减法一律转换为加法。
需要判断符号是否相同:
如果相同,结果符号不变,并进行绝对值相加
如果不同,结果取绝对值大的数的符号,并进行绝对值相减
2009-8-17
9原码、反码和补码
正数,原码、反码、补码相同
– 符号位为 0,数值为对应的二进制数。
+ 109
[01101101]原 = [01101101]反 = [01101101]补
负数,
– 原码 符号位为 1,数值为绝对值的二进制数。 - 109 [11101101]原
– 反码 符号位为 1,数值为绝对值的二进制数各位变反。 - 109 [10010010]反
– 补码 符号位为 1,数值为绝对值的二进制数各位变反加 1。 - 109 [10010011]补
2009-8-17
102,有符号和无符号整型数据
– 有符号的整型数据 signed int
– 无符号的整型数据 unsigned int
区别是将 最高位 看作符号位还是数据位例如,1111 1111 1010 1000
作为 有符号数 使用时,最高为符号位为负数,值是,- 88(再求一次补)
作为 无符号数 使用时,最高为数据位为无符号的数,值是,65448
2009-8-17
11例如:
main( )
{ unsigned int m;
m= 65448;
printf("\nm=%d\n",m);
printf("m=%u\n",m);
}
例
jc2_a
输出结果:
m=-88
m=65448
按有符号数输出按无符号数输出
2009-8-17
12整型数据的类型及规定
方括号表示可选项
int 分配 2 Byte,long分配 4 Byte
类型名称 类型符 bit 取值范围整型
(短整型 )
[signed] int
[signed] short [int]
16 -215~ 215-1
(-32768~ 32767 )
无符号整型 unsigned [int] 16 0 ~ 2
16-1
(0~ 65535 )
长整型 [signed] long [int] 32 -231~ 231- 1
无符号长整型 unsigned long [int] 32 0 ~ 232-1
2009-8-17
132.1.2 实型数据
1.实型数据的类型
– 单精度实型数据 float,分配 4 Byte
– 双精度实型数据 double,分配 8 Byte
2.实型数据的存储单精度实型指数部分小数部分小数的符号位 指数的符号位
2009-8-17
14实型数据的类型及规定
C标准并未具体规定各种实型数据所占字节数,也不规定具体小数和指数部分的位数。
一般而言,小数部分位数多,数据表示的有效数字多,
精度就高;而指数部分位数多,则表示的数据范围更大。
有效数字的意义?
类型 类型符 Byte 绝对值的范围 有效数字单精度型 float 4 10-37 ~ 1038 7~ 8 位双精度型 double 8 10-307 ~10308 15~ 16位例 jC2_a
2009-8-17
152.1.3 字符型数据
字符型数据 char,分配 1 Byte
字符型数据是指字母、数字、各种符号等用 ASCII值表示的字符
例如 'a' 是一个 char类型数据,称作字符常量,存储:
0 1 1 0 0 0 0 1
2.1.4 空类型
空类型 void
通常与指针或函数结合使用
2009-8-17
162.2 常量、变量与标准函数
主要内容:
– 常量
– 变量
– 标准库函数
2009-8-17
172.2.1 常量
在运行程序的过程中值保持不变的量
1.整型常量
– 十进制,0~9
– 八进制,0~7,以 0开头
– 十六进制,0~9,A~F/a~f,以 0x或 0X 开头例如:
100 -8 0 +123
010 024 0100 073
0x38 0x10 0X10 0XFF 0x0a
2009-8-17
181,整型常量
整型常量的类型:
– 根据值大小默认类型。
– 整型常量后面加 l或 L,则认为是 long int型例如,123L,0L,432l,0x100l
注意:
十六进制常量中可以使用大写字母 A~ F,
也可以使用小写字母 a~ f。
八进制常量中不能出现数字 8 或 9
例如,018,0921非法
2009-8-17
192,实型常量
– 十进制形式
1.0 1,+12.0 -12.0 0.0
– 指数形式
1e3 1.8e-3 -123E-6 -.1E-3
等价于,1× 103 1.8× 10-3 -123× 10-6 -0.1× 10-3
指数只能是整数,而尾数则可以是整数也可以是小数,无论指数或尾数均不能省略例如,1e,E.5,E-3 非法
实型常量的类型:默认为 double型,后面加 F
( 或 f),则强调表示该数是 float类型例如,3.5f,1e2F
2009-8-17
203,字符型常量
可视字符常量
– 单引号括起来的单个可视字符例如,'a','A','+','3',' ' 等
转义字符常量
– 单引号括起来的 \与 可视字符 组合,例如:
\0 字符串结束标志
\n 回车换行
\t 跳到下一个输出位置
\" 双引号字符
\ddd ddd为 1到 3位八进制数所代表的字符
\xhh hh为 1到 2位十六进制数所代表的字符
2009-8-17
214,字符串常量
用双引号括起的一个字符序列
– 例如,"ABC","123","a","\n\t "
"\nGood morning"
字符串常量的长度,
– 所包含的字符个数
字符串常量的存储方式:
\n G o o d m o r n i n g \0
a \0
所占存储单元数,串长度+ 1
例如:
字符串结束标记
2009-8-17
225,符号常量
以标识符来代表的常量
事先编译预处理命令 define定义
编译时先由系统替换为它所代表的常量,再进行编译例如:
#define LEN 2.5
main( )
{ float a,b;
a= 2*3.14 *LEN;
b=3.14*LEN*LEN;
printf("a=%f,b=%f\n",a,b);
}
定义符号常量使用符号常量编译前系统进行替换
2009-8-17
235,符号常量
main( )
{ float a,b;
a= 2*3.14 *2.5;
b=3.14*2.5*2.5;
printf("a=%f,b=%f\n",a,b);
}
define是编译预处理命令,必须以,#”开头
编译预处理命令在第 7章讨论。
替换为
2009-8-17
242.2.2 变量
1,变量的有关概念
在程序运行过程中,其值改变的数据,称为变量,变量用标识符表示,称为 变量名 。
变量必须“先定义后使用”
系统为变量分配存储单元,存储变量的值。
编写程序时通过变量名来存、取 变量值 。
a
510 变量值为变量分配的存储单元变量名例如:
有 变量 a
它的值是 510
2009-8-17
252,变量定义变量定义的一般格式:
数据类型说明符 变量列表 ;
例如,int i,j;
long k,m;
float x,y;
char ch1,ch2;
必须使用合法的标识符作变量名
不能使用关键字为变量命名
2009-8-17
263,变量的初始化:
允许在说明变量的时候对变量赋初值。
例如,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;
2009-8-17
272.2.3 标准库函数
由 C编译系统定义的一种函数,存放在系统函数库中,用户可以根据需要随时调用
常用函数如,printf,scanf,fabs,sqrt,sin、
(常用数学函数参见教材 P30表 2.5 )
函数调用形式,
函数名([参数表])
例如,putchar('a')
sqrt(x) 例 jc2_3
2009-8-17
282.3 运算符和表达式
主要内容:
– 算术运算符和算术表达式
– 赋值运算符和赋值表达式
– 关系运算符和关系表达式
– 逻辑运算符和逻辑表达式
– 位运算符和位运算表达式
– 条件运算符和条件表达式
– 逗号运算符和逗号表达式
– 其他运算符及其运算
2009-8-17
29运算符的有关概念
作用:
– 对运算对象完成规定的操作运算
类型:
– 按运算对象分:
单目、双目、三目
– 按功能分:
算术、赋值、关系、逻辑
条件、逗号、位、其他
2009-8-17
30运算符的优先级和结合性
优先级
– 指各种运算符号的运算优先顺序例如,算术运算优先于关系运算算术运算中先 * / 后 + -
结合性
– 指运算符号和运算对象的结合方向
– 分为:从左向右 (左结合 )和从右向左 (右结合 )
例如,算术运算符为 左结合 a-b+4
赋值运算符为 右结合 a= b = 5
( C语言规定见教材 P297 附录 B)
2009-8-17
31本章涉及的运算符
+ - * / % ++ -- + -
= += -= *= /= %=
&= |= ^= >>= <<=
> < >= <= == !=
&& || !
& | ^ ~ << >>
:
,
& sizeof (数据类型标识符 )
类型 种类算术运算符赋值运算符关系运算符逻辑运算符位运算符条件运算符逗号运算符其他运算符
2009-8-17
32表达式的有关概念
什么是表达式
– 由 运算符 将运算对象连接成的式子,它描述了一个具体的求值运算过程。
计算表达式的值
– 按照运算符的运算规则求值
– 求值时注意运算符的优先级和结合性
表达式值的类型
– 自动转换
– 强制转换
2009-8-17
33例如:
表达式:
150+'b'*2- 12.456
b=(++a)-2
a /= a *= (a = 2)
f=a>b>c
--a ||++b&&c++
max=a>b? a,b
a=3,a+=3,a*a
1/(float)a+6
2009-8-17
34算术运算
算术运算符的优先级
( ) + - ++ -- * / % + -
同级 同级 同级单目 双目高 低
没有乘方运算符,要计算 a3要写作 a*a*a 的连乘,
或用标准库函数 pow(a,3)
―/‖的运算对象可为各种类型数据,但是当进行两个整型数据相除时,运算结果也是整型数据
,%”要求运算对象必须是整型数据,功能是求两数相除的余数,余数的符号与被除数的符号相同。
2009-8-17
35自增自减运算
++ --是 单目运算符
有前缀和后缀 两种形式
– 前缀形式,先自增 (自减 )再引用;
– 后缀形式,先引用再自增 (自减 );
功能:
前缀形式 ++ a 等价于 a = a + 1
-- a 等价于 a = a – 1
后缀形式 a ++ 等价于 a = a + 1
a -- 等价于 a = a – 1
表达式的值会不同
2009-8-17
36例如:
当 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
2009-8-17
37说明:
++ 和 -- 的运算对象只能是变量(或运算结果是变量的表达式),不能是常量(或运算结果是数值的表达式)。
例如,5++,(a+2)++ 不合法。
具有右结合性,结合方向为从右到左。
例如,–a++ 等价于 -(a++)
如果有多个运算符连续出现时,C系统尽可能多的从左到右将字符组合成一个运算符例如,i +++ j 等价于 ( i++)+j
-i+++-j 等价于 -(i++)+(-j)
2009-8-17
38
main( )
{ int a=5;
printf("%d %d\n",a,a++ );
}
说明(续):
对函数参数的求值顺序:
– Turbo C系统先计算最右边的参数值,
再依次计算左面的参数值。
【例 2.5】有多个函数参数且为同一变量自增的运算处理。
输出结果:
6 5
运行例 2.5
2009-8-17
39说明 ( 续 ),
【例 2.6】有多个函数参数且为同一变量多次自增的运算处理。
main( )
{ int a=5;
printf("%d%d\n",a,(a++)+( a++));
}
输出结果:
7 11
运行例 2.6
2009-8-17
40赋值运算
赋值运算符 (右结合)
= += -= *= /= %=
&= |= ^= >>= <<=
赋值表达式
– 将 表达式的值 存入 变量 对应的内存单元中
m=12
b=(++a)-2
m%=3+n 等价于 m=m%(3+n)
x *= (x = 5)
2009-8-17
41说明:
赋值号左边必须是变量,右边可以是 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
2009-8-17
42关系运算
关系运算符 (左结合)
> >= < <= == !=
较高 较低
关系表达式
– 用关系运算符将运算对象连接成的式子例如,12< 'C'+1 ( 字符型数据比较 ASCII值)
a==b>=c 等价于 a == ( b>=c )
与 (a==b)>=c 不等价
关系运算符优先于赋值,低于算术
2009-8-17
43说明:
关系运算的结果应该是 逻辑值 。 C语言用数值用 1 表示 逻辑真,0 表示 逻辑假例如,7>5 的值是 1,5>7 的值是 0
'a'>'b'的值是 0,'a'<'b' 的值是 1
即关系表达式的值,0 或 1
实型数 可进行大于或小于比较,但通常不进行 == 或 != 的关系运算
2009-8-17
44逻辑运算符
逻辑运算符
&& || !
逻辑运算符的运算规则运算对象 逻辑运算结果
a b a&&b a || b !a
非 0 非 0 1 1 0
非 0 0 0 1 0
0 非 0 0 1 1
0 0 0 0 1
2009-8-17
45逻辑表达式
逻辑表达式
– 用逻辑运算符将运算对象连接成的式子例如,0&&'b'
a &&b || c&&d
a || b-5 || c/4
!x+y >= z
逻辑运算符的优先级 和结合性:
– !是单目运算符,右结合,高于算术
– && 和 || 是双目运算符,左结合,高于赋值运算符,低于关系运算符
2009-8-17
46逻辑运算规则
从左到右依次进行逻辑计算
– 运算对象为 非 0表示 逻辑真
– 运算对象为 0 表示 逻辑假
逻辑运算的结果为 0 或 1
例如设,a=15,b=0,c=-2
a && b && c 结果为 0
a || b || c 结果为 1
(a+c) || b && c 结果为 1
2009-8-17
47逻辑运算规则 ( 续 )
运算按照 从左至右 的顺序进行,一旦能够确定逻辑表达式的值,就立即结束运算
——逻辑运算的短路性质例如 设,a=1,b=0,c=-2
a && b && c
(a++) || ++ b&& --c
为 0,运算终止,表达式 值 为 0
为非 0,运算终止,表达式值为 1
且 a为 2,b为 0,c为 -2 (b,c保持原值 )
2009-8-17
48关系与逻辑运算符的应用
表示数学公式 a>b>c
判断 a,b,c三条线段能否组成一个三角形
a,b不同时为负
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)
a>b && b>c
2009-8-17
49位运算符
~ & ^ | << >>
位逻辑运算符 移位运算符单目
位运算符的运算对象只能是 整型数据 或字符型数据,不能是实型数据
运算对象一律按二进制补码参加运算,
并 按位进行运算
位运算的结果是一个整型数据低于单目、算术运算符,
高于其他运算符低于单目、算术和关系运算符,高于其他运算符
2009-8-17
50位逻辑运算符的运算规则
假设 ai和 bi均是一个二进制位( bit)
运算对象 逻辑运算结果
ai bi ai&bi ai|bi ai ^bi?ai
0 0 0 0 0 1
0 1 0 1 1 1
1 0 0 1 1 0
1 1 1 1 0 0
例如,假设 a=10,b=010
求 a&b,a | b,a^b,?a
2009-8-17
51程序如下:
main( )
{ int a=10,b=010;
printf("%d %d\n",a&b,a|b);
printf("%d %d\n",a^b,~a);
}
输出结果:
8 10
2 -11
0000 0000 0000 1010
& 0000 0000 0000 1000
0000 0000 0000 1000
即,a&b的值是 8
0000 0000 0000 1010
1111 1111 1111 0101
即,?a的值是 -11
运行 jc2_b
2009-8-17
52移位运算
例如:
a<<b
a+8>>b-1 等价于 (a+8)>>(b-1)
例如,假设 a=10,b=2,求 a<<b,a+8>>b-1
main( )
{ int a=10,b=2;
printf("%d %d\n",a<<b,a+8>>b-1);
}
输出结果:
40 9
运行 jc2_c
请自行分析运行结果
2009-8-17
53条件表达式运算
条件运算符,?,
条件表达式的一般形式表达式 1? 表达式 2,表达式 3
例如,m<n? x,a+3
a++>=10 && b-->20? a,b
x=3+a>5? 100,200
C语言中唯一的 三目运算符,要正确区分用? 和,分隔的表达式
涉及条件运算符的优先级与结合性
2009-8-17
54条件运算符优先级
条件运算符优先级高于赋值、逗号运算符,
低于其他运算符例如:
⑴ 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 )
2009-8-17
55条件运算符的结合性
条件运算符具有 右结合性
当一个表达式中出现多个条件运算符时,
应该将位于最右边的问号与离它最近的冒号 配对,并按这一原则正确区分各条件运算符的运算对象。
例如,w<x? x+w,x<y? x,y
与 w<x? x+w,( x<y? x,y) 等价与 (w<x? x+w,x<y)? x,y 不等价
2009-8-17
56逗号表达式运算
逗号表达式的一般形式表达式 1,表达式 2,……,表达式 n
逗号表达式的值
– 从左向右,依次对表达式求值,最后得到 表达式 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
2009-8-17
57取地址运算符 &
– 为单目运算符
– 运算对象只能是变量
– 运算结果是变量的存储地址例如有定义,
int a,student;
char ch;
可以对变量 a,ch,student 进行 &运算:
&a &ch &student
2009-8-17
58长度运算符 sizeof
– 为单目运算符
– 运算对象只能是 变量名 或 数据类型标识符
– 运算结果为该变量或该数据类型的长度
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));
}
输出结果:
2 2 8 8 4 1
运行 jc2_d
2009-8-17
592.4 运算中数据类型的转换
2.4.1 数据类型的自动转换
转换原则,自动将精度低、表示范围小的运算对象类型向精度高、表示范围大的运算对象类型转换
char,short
double
long
float
unsigned
int
高精度低精度例如有定义:
int a; char ch;
表达式:
a-ch*2+35L
a-ch*2+ 35.
2009-8-17
602,赋值运算中的类型转换
<实型变量 > = <整型表达式 >
– 小数部分自动补 0
<整型变量 > = <实型表达式 >
– 自动舍去实型表达式的小数部分( 注意不进行四舍五入 )
<字符变量 > = <整型表达式 >
<整型变量 > = <长整型表达式 >
– 自动截取表达式值的低字节赋值,舍去高字节
<整型变量 > = <字符数据 >
<长整型变量 > = <整型表达式 >
– 自动给高字节补 0 或 补 1
2009-8-17
612.4.2 数据类型的强制转换
强制转换的一般形式
(类型名 ) 表达式例如,(int)( 'b'+3*x)%3
1/(float)a+6
注意:
(float) 22/5 与 (float) (22/5) 不同
错误的类型转换:
(int) b=a+5
b= int (3*a)