白 雪 飞
baixf@ustc.edu.cn
中国科学技术大学电子科学与技术系
Dept,of Elec,Sci,& Tech.,USTC
Fall,2003
第 2章 数据类型、运算符和表达式
C语言程序设计 - 第 2章 数据类型、运算符和表达式 2
目 录
? 数据类型、常量和变量的定义
? 运算符的种类、优先级和结合方向
? 表达式的类型和求值
? 简单的 C程序设计及基本输入输出
C语言程序设计 - 第 2章 数据类型、运算符和表达式 3
C的数据类型 (Data Types)
? 基本类型
?整型、字符型、浮点型(实型)、枚举类型
? 构造类型
?数组类型、结构体类型、共用体类型
? 指针类型
? 空类型
C语言程序设计 - 第 2章 数据类型、运算符和表达式 4
数据类型、常量和变量
? C的数据结构是以数据类型形式出现的
? 由前述数据类型可以构造出更复杂的数
据结构
? C语言的数据有常量和变量之分
? 常量和变量都分别属于某一数据类型
? 程序中用到的所有数据都必须指定类型
? 本章仅介绍基本数据类型
C语言程序设计 - 第 2章 数据类型、运算符和表达式 5
标识符 (Identifier)
? 标识符
?变量名、符号常量名、函数名、类型名 …
? 标识符命名规范
?由字母、数字、下划线 (Underscore,'_')组成
?第一个字符必须为字母或下划线
? C语言标识符是大小写敏感的
?标识符的名称一般应具有一定的含义
?不要与 C语言关键字 (Keywords)重复
?一般不要使用以下划线开头的标识符
C语言程序设计 - 第 2章 数据类型、运算符和表达式 6
标识符示例
? 正确的标识符
?student,num1,_SUM,_1_2_3
?MyName,myname,my_name
? 错误的标识符
?room3-1 包含了其他字符(减号)
?2men 以数字开头
?long 与关键字重复
?Mr.Zhu 包含了其他字符(小数点)
C语言程序设计 - 第 2章 数据类型、运算符和表达式 7
常量 (Constants)
? 常量
?程序运行过程中,其值不能被改变的量
?例如,12,-6.7,'a'…
? 符号常量 (Symbolic Constants)
?用一个标识符代表的常量
?相当于把标识符用一个常量简单替换下来
?标识符是一个整体,不要试图拆开来替换
?含义清楚,一改全改
?习惯上符号常量名用大写字母
C语言程序设计 - 第 2章 数据类型、运算符和表达式 8
常量示例
#define PRICE 30
#define NUM 12
void main()
{
...,..
total = NUM * PRICE;
total2 = 84 * PRICE2;
printf("total=%d",total);
...,..
} 不会被替换
=> total = 12 * 30;
常量
符号常量
C语言程序设计 - 第 2章 数据类型、运算符和表达式 9
变量 (Variables)
? 其值可以改变的量称为变量
? 变量有一个名字,即标识符
? 变量在存储器中占据一定的存储单元
? 变量占据存储空间的大小由其类型决定
? 变量名表示存储变量的存储单元地址
? 程序使用变量名表示这个变量所占据的
存储单元里 存储的数据的值
? 变量要“先定义,后使用”
C语言程序设计 - 第 2章 数据类型、运算符和表达式 10
变量的存储
34
a 变量名
存储单元 (地址 )
变量值
C语言程序设计 - 第 2章 数据类型、运算符和表达式 11
整型 (Integer)
? 整型常量的表示方法
? 整型变量
?整型数据在内存中的存放形式
?整型变量的类型
?整型变量的定义
?整型数据的溢出
? 整型常量的类型
C语言程序设计 - 第 2章 数据类型、运算符和表达式 12
整型常量的表示方法
? 十进制 (Decimal)
?例如,123,-456,0
? 八进制 (Octal)
?以 0开头,不得含有 8或 9
?例如,0123,-0456
?错例,0138,-0912
? 十六进制 (Hexadecimal)
?以 0x或 0X开头,用 a~f或 A~F表示 10~15
?例如,0x123,-0X45,0x3AB,-0xabc
C语言程序设计 - 第 2章 数据类型、运算符和表达式 13
整型数据在内存中的存放方式
? 二进制形式
?举例,int i=50; /*int类型占 2字节 */
? 补码 (Complement)
?正数:与原码一致,首位为 0
?负数:绝对值取反加一,首位为 1
?零:各位全为 0
0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 0
高地址字节 低地址字节
C语言程序设计 - 第 2章 数据类型、运算符和表达式 14
补码举例
? 举例
?int i=-50; /*int类型占 2字节 */
0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 0
1 1 1 1 1 1 1 1 1 1 0 0 1 1 0 1
1 1 1 1 1 1 1 1 1 1 0 0 1 1 1 0
50的原码
-50的补码
取反
加一
C语言程序设计 - 第 2章 数据类型、运算符和表达式 15
整型变量的分类
? 按占用存储空间的大小划分
?基本整型 int
?短整型 short [int]
?长整型 long [int]
? 按有无符号划分
?有符号 [signed]
?无符号 unsigned
? 上述两种分类方式组合,可得到 6种类型
C语言程序设计 - 第 2章 数据类型、运算符和表达式 16
整数的长度
? 整数的类型与长度
?short:占 2字节( 16bit)
?long,占 4字节( 32bit)
?int,占 2或 4字节( 16或 32bit)
? 2Bytes = short ≤ int ≤ long = 4Bytes
?若需要精确的长度,可选用 short或 long
? 举例
? BC3.1:int长度为 2Bytes
? gcc,int长度为 4Bytes
C语言程序设计 - 第 2章 数据类型、运算符和表达式 17
有符号数与无符号数
? 有符号数
?二进制补码表示,首位为符号位
?指定 signed或缺省情况,即为有符号数
? 无符号数
?没有符号位,只能表示非负数
?无符号数类型必须指定为 unsigned
?若把负数赋值给无符号数,则把该负数的补
码当作无符号数进行处理
C语言程序设计 - 第 2章 数据类型、运算符和表达式 18
有符号数与无符号数举例
void main()
{
int i;
unsigned j;
i=j=-50;
i=i/2; /*-25*/
j=j/2; /*32743*/
}
1 1 1 1 1 1 1 1 1 1 0 0 1 1 1 0
-50的补码 i,j
/ 2
1 1 1 1 1 1 1 1 1 1 1 0 0 1 1 1
0 1 1 1 1 1 1 1 1 1 1 0 0 1 1 1
i/2-25的补码
j/232743的补码 /原码
C语言程序设计 - 第 2章 数据类型、运算符和表达式 19
整型数据的取值范围
类 型 长度 (bit) 取值范围
[signed] short [int] 16 -215 ~ 215-1
unsigned short [int] 16 0 ~ 216-1
[signed] int 16 or 32 -215(31) ~ 215(31)-1
unsigned [int] 16 or 32 0 ~ 216(32)-1
[signed] long [int] 32 -231 ~ 231-1
unsigned long [int] 32 0 ~ 232-1
C语言程序设计 - 第 2章 数据类型、运算符和表达式 20
整型变量的定义 (Definition)
? 定义形式
?int a,b;
?unsigned c;
?long d;
?unsigned short e;
? 变量的定义一般放在一个函数开头的声
明部分,关于变量定义的具体内容在以
后相关章节里详细介绍
C语言程序设计 - 第 2章 数据类型、运算符和表达式 21
整型变量的定义与使用举例
void main()
{
int a; /*定义有符号基本整型变量 a*/
unsigned b;/*定义无符号基本整型变量 b*/
long c; /*定义有符号长整型变量 c*/
a = -23; /*a的值为 -23*/
b = 45; /*b的值为 45*/
c = a + b; /*c的值为 22*/
}
C语言程序设计 - 第 2章 数据类型、运算符和表达式 22
整型数据的溢出 (Overflow)
? 溢出
?数据超出了变量能够存储的范围,造成数据
丢失或数值改变等
? 举例
void main()
{
int a = 32767;
a++; /*32768?*/
}
0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+1
32767的补码
-32768的补码
C语言程序设计 - 第 2章 数据类型、运算符和表达式 23
整型常量的类型
? 常量的类型后缀 (Suffix)
?l,L 表示常量是一个长整型
?u,U 表示常量是一个无符号整型数
?两种后缀可以一起使用
? 举例
?123l 长整型常数 123
?456U 无符号整型常数 456
?789ul无符号长整型常数 789
?101Lu无符号长整型常数 101
C语言程序设计 - 第 2章 数据类型、运算符和表达式 24
整型常量使用中的类型问题
? 对整型变量赋值
?常量的值不要超过变量的取值范围
? 直接使用常量
?带有 l,L,u,U等后缀的整型常量一般用
于函数调用
?不带有后缀的整型常量的类型,是根据其数
值大小所处的范围来确定的
C语言程序设计 - 第 2章 数据类型、运算符和表达式 25
浮点型 (Floating Point)
? 浮点型常量的表示方法
? 浮点型变量
?浮点型数据在内存中的存放形式
?浮点型变量的类型
?浮点型数据的舍入误差
? 浮点型常数的类型
C语言程序设计 - 第 2章 数据类型、运算符和表达式 26
浮点型常量的表示方法
? 十进制小数形式
?由符号、数字和小数点 (必须 )组成
?整数和小数部分都可省略,但不能同时省略
?举例,12.3,-.123,123.,0.,.0
? 指数形式
?由整数 (或小数 ),e(或 E)、整数顺序组成
?e或 E之前必须有数字,之后必须是整数
?举例,123.4e-5表示 123.4× 10-5
?错例,e1,12e,1.2e3.4,.e5,e
C语言程序设计 - 第 2章 数据类型、运算符和表达式 27
规范化指数形式
? 规范化指数形式
?类似于“科学计数法”
?e或 E之前的小数中,小数点前面有且仅有一
个非零数字
? 举例,123.456
?规范化形式,1.23456e2,1.23456E+002
?非规范化形式,123.456,12.3456e1、
12345.6e-2,0.123456e3、
12345600e-5…
C语言程序设计 - 第 2章 数据类型、运算符和表达式 28
浮点型数据在内存中的存放方式
? 二进制规范化指数形式
? 小数部分长度与能表示的精度有关
? 指数部分长度与能表示的数值范围有关
1 1 0 1 1 0 0 1 1 0 1 1 0 0 1 0
指数部分 e 小数部分 f符号 s
es fv 2).1()1( ???
C语言程序设计 - 第 2章 数据类型、运算符和表达式 29
几个特殊的数
? 无穷大 (Infinition)
?Inf 举例,1.0/0.0
?-Inf 举例,-1.0/0.0
? NaN (Not a Number)
?NaN 举例,sqrt(-1) /*开平方 */
?-NaN 举例,-sqrt(-1)
? 零 (Zero)
?浮点数用特殊的形式表示零
C语言程序设计 - 第 2章 数据类型、运算符和表达式 30
浮点型变量的类型
? 分类
?单精度 float
?双精度 double
?长双精度 long double
? 长度和取值范围
类 型 长度 (bit) 有效数字 绝对值范围
float 32 6~7 10-37~1038
double 64 15~16 10-307~10308
long double 128 18~19 10-4931~104932
C语言程序设计 - 第 2章 数据类型、运算符和表达式 31
浮点型数据的舍入误差
? 由于浮点型变量能够表示的有效数字有
限,将有效位以外的数字舍去造成误差
? 举例
float a=123456.789e5,b;
b = a + 20; /*b=12345678920?*/
printf("a=%f\nb=%f\n",a,b);
运行结果 > a=12345678848.000000
b=12345678848.000000
?思考,1.0/3*3=?
C语言程序设计 - 第 2章 数据类型、运算符和表达式 32
浮点型常量的类型
? 类型后缀
?f,F 表示常量是一个单精度型浮点数
?l,L 表示常量是一个长双精度型浮点数
?无任何后缀的浮点型常量视作双精度型
? 对浮点型变量赋值
?一个浮点型常量可以赋值给任何类型的浮点
型变量
?根据变量类型截取常量的相应有效数字
?注意防止出现溢出
C语言程序设计 - 第 2章 数据类型、运算符和表达式 33
字符型 (Character)
? 字符型常量
? 字符型变量
? 字符型数据在内存中的存放形式
? 字符型数据的使用方法
? 字符串常量
C语言程序设计 - 第 2章 数据类型、运算符和表达式 34
字符型常量
? 单引号括起来的 一个 字符
?举例,'a','A','1','?','?'…
?错例,'abc','','我 '…
? 转义字符
?以 '\'开头的特殊字符
?'\ddd' 1到 3位 8进制数 ASCII码代表的字符
?'\xhh' 1到 2位 16进制数 ASCII码代表的字符
?举例,'\n','\t','\\','\'','\"'、
'\123','\x3A'…
C语言程序设计 - 第 2章 数据类型、运算符和表达式 35
字符型变量
? 字符型变量只能存放 一个 字符
? 定义与使用
void main()
{
char c1,c2; /*定义字符型变量 c1和 c2*/
c1 = 'a'; /*c1的值为 'a'*/
c2 = '2'; /*c2的值为 '2'*/
}
C语言程序设计 - 第 2章 数据类型、运算符和表达式 36
字符型数据在内存中的存放形式
? 一个字符型数据占一个字节的空间
? 字符型数据以其 ASCII码形式存放
? 字符型数据的存放形式与只占一个字节
长度的整型数据完全相同
01100001
c1='a'
(ASCII=97)
00110010
c1='2'
(ASCII=50)
C语言程序设计 - 第 2章 数据类型、运算符和表达式 37
字符型数据的使用方法
? 可以把字符型数据视作一种长度为 1字节
的整型数据处理
?当使用字符型数据时,与使用这个字符的
ASCII码 (一个 8位整数 )是完全一样的
?字符型数据的用法与整型数据完全一样,包
括运算、赋值、输入、输出等
?字符型数据使用过程中,同样需要注意溢出、
符号等问题
? 是字符还是整数,只有在输出时才有意义
C语言程序设计 - 第 2章 数据类型、运算符和表达式 38
字符型数据使用举例
void main()
{
char c;
int i,j;
c = 97; /*c = 'a'*/
i = c + 20;/*i = 117*/
j = '2'; /*j = 50*/
printf("%c,%d\n",c,c); /*a,97*/
}
C语言程序设计 - 第 2章 数据类型、运算符和表达式 39
字符型变量的符号
? 字符型变量与整型变量一样,也分为有
符号数与无符号数
? 无符号字符
?unsigned char c;
?举例,表示一个班级的人数 (<256)
? 赋值和使用中需要注意的问题,与整型
变量相同
C语言程序设计 - 第 2章 数据类型、运算符和表达式 40
字符串 (String)常量
? 表示形式
?一对双引号括起来的字符序列
?引号内可以包括 0个,1个或多个字符
?字符序列中的特殊字符用转义字符表示
?举例,"abc","a","","?","我 "
?举例,"12.4","$#*!","C:\\HOME"
? 字符常量和字符串常量是不同类型的数据
?例如,'a'与 "a"是不同的
?不能把一个字符串赋值给一个字符型变量
C语言程序设计 - 第 2章 数据类型、运算符和表达式 41
字符串在内存中的存放方式
? 在内存中每个字符按顺序存放
? 字符串结尾有一个 空字符 (ASCII=0,'\0')
作为字符串结束标志
? 字符串结束标志 '\0'是不能显示的,在
字符串常量中,也不用显式写出来
? 举例
?"TEST"
?""
?"a"
'T''E''S' 'T' \0 84 69 83 84 00
\0
'a' \0
00
97 00
C语言程序设计 - 第 2章 数据类型、运算符和表达式 42
变量赋初值 (Initialization)
? 在定义变量的同时对变量赋值 (初始化 )
? 举例
?int a=1;
/*相当于 int a; a=1;*/
?int a,b=3;
/*对 b赋初值,a没有初值 */
?int b,c,a=b=c=100;
/*对三个变量赋同样的初值 */
? 变量使用前,一般应先对它赋值
C语言程序设计 - 第 2章 数据类型、运算符和表达式 43
各类数值型数据间的混合运算
? 整型、字符型、浮点型数据可混合运算
? 混合运算时,不同类型的数据按照一定
的规则先转换为同一类型,然后再运算
double
long
unsigned
int
float
char,short
高
低
C语言程序设计 - 第 2章 数据类型、运算符和表达式 44
运算符 (Operator)
? 运算符的种类
? 运算符的优先级
? 运算符的结合方向
C语言程序设计 - 第 2章 数据类型、运算符和表达式 45
运算符的种类 (1)
? 算术运算符 + - * / % ++ --
? 关系运算符 > < == >= <= !=
? 逻辑运算符 ! && ||
? 位运算符 << >> ~ | ^ &
? 赋值运算符 = += -= *= /= %=
>>= <<= &= ^= |=
? 条件运算符?:
C语言程序设计 - 第 2章 数据类型、运算符和表达式 46
运算符的种类 (2)
? 逗号运算符,
? 指针运算符 * &
? 求字节数运算符 sizeof
? 强制类型转换运算符 (type)
? 分量运算符, ->
? 下标运算符 []
? 其他运算符 ()
C语言程序设计 - 第 2章 数据类型、运算符和表达式 47
运算符的优先级 (Precedence)
? 优先级
?运算符的运算次序按优先级由高到低执行
?可以用圆括号 ( )改变运算符的执行次序
? 举例
?a+b*c–d/e
/*先算乘除,后算加减 */
/*乘除比加减优先级高 */
?(a+b)*(c-d)/e
/*先算加减,后算乘除 */
C语言程序设计 - 第 2章 数据类型、运算符和表达式 48
运算符的结合方向 (Associativity)
? 结合方向
?当一个操作数两侧的运算符优先级相同时,
运算次序按照结合方向的规定进行
? 举例
?a+b-c
/*+和 -的结合方向都是从左向右 */
/*b先与 +结合计算 a+b,然后执行减法 */
?a=b=1
/*=的结合方向是从右向左,先计算 b=1*/
C语言程序设计 - 第 2章 数据类型、运算符和表达式 49
运算符的结合方向规则
? 单目运算符的结合方向都是“从右向左”
?!,~,++,--,+(正号 ),-(负号 )
?*(指针运算符 ),&(地址运算符 )
?sizeof,(type)
? 赋值运算符的结合方向是“从右向左”
? 三目运算符的结合方向是“从右向左”
?唯一的三目运算符:条件运算符?:
? 其他运算符的结合方向都是“从左向右”
C语言程序设计 - 第 2章 数据类型、运算符和表达式 50
优先级与结合方向总结
? 不同优先级的运算符,运算次序按优先
级由高到低执行
? 同一优先级的运算符,运算次序按结合
方向的规定执行
? 可以使用圆括号 ( )明确运算次序
?圆括号 ()具有最高的优先级
C语言程序设计 - 第 2章 数据类型、运算符和表达式 51
表达式 (Expression)
? 表达式的概念
? 表达式的类型
? 表达式求值
?算术运算符和算术表达式
?赋值运算符和赋值表达式
?逗号运算符和逗号表达式
C语言程序设计 - 第 2章 数据类型、运算符和表达式 52
表达式的概念
? 表达式
?用运算符把操作数连接起来,并符合 C语言
语法规则的式子
?操作数包括常量、变量、函数调用、表达式
?广义上,常量、变量、函数调用也可以看作
属于表达式的范畴
? 举例
?a+2.5*b-6/c+'z'-max(x,y)
?!((a<1e-6)&&(b==(c+sqrt(f))))
C语言程序设计 - 第 2章 数据类型、运算符和表达式 53
表达式的类型
? 表达式的类型
?表达式的值的类型
?取决于操作数的类型以及它们所做的运算
? 举例
?a+2.5*b-6/c+'z'
/*混合类型算术运算,值为 double类型 */
?!((a<1e-6)&&(b==(c+sqrt(f))))
/*逻辑判断的结果是逻辑值 */
/*C语言用整型表示逻辑类型 */
C语言程序设计 - 第 2章 数据类型、运算符和表达式 54
算术运算符 (Arithmetic Operators)
? 基本算术运算符
?+ - * / %
? 强制类型转换运算符
?(类型名 )
? 自增、自减运算符
?++ --
C语言程序设计 - 第 2章 数据类型、运算符和表达式 55
基本算术运算符
运算符 名称 举例 说明
+ 正值运算符 (正号 ) +b 值不变
- 负值运算符 (负号 ) -d 取相反数
+ 加法运算符 a+3 加法
- 减法运算符 c-4 减法
* 乘法运算符 a*3 乘法
/ 除法运算符 c/d 除法
% 模运算符 e%4 求余数、取模
C语言程序设计 - 第 2章 数据类型、运算符和表达式 56
基本算术运算符的特性
? 优先级 (从高到低 )
?+ (正号 ) – (负号 )
?* / %
?+ (加 ) – (减 )
? 结合方向
?+ (正号 ) – (负号 ):从右向左
?+ (加 ) – (减 ) * / %,从左向右
C语言程序设计 - 第 2章 数据类型、运算符和表达式 57
基本算术运算符的说明
? 两个整数相除,结果也为整数
?直接舍去商的小数部分,而不会“四舍五入”
?负数整数除法,结果的舍入方向没有规定
?如果需要得到精确的运算结果,可以把其中
一个操作数转换为浮点数
?举例,5/3(=1),5.0/3(=1.66666…)
?举例,-5/3(=-1?-2?)
? 模运算符的两个操作数都必须是整数
?负数模运算结果的符号没有规定
?举例,5%3(=2),-5%3(=-2?1?)
C语言程序设计 - 第 2章 数据类型、运算符和表达式 58
强制类型转换运算符
? 形式
?(类型名 )操作数
? 说明
?强制把表达式转换成所需的类型
?强制类型转换运算符的优先级比较高
?强制类型转换不会改变操作数自身的类型,
只是得到一个所需类型的中间量
?多用于自动类型转换不能实现的目的
?强制类型转换后,会影响 C语言做类型检查
C语言程序设计 - 第 2章 数据类型、运算符和表达式 59
强制类型转换举例
float x=2.8,y=3.7,z;
int a,b,c,d=5,e=2;
a=(int)x+y; /* a=5,2+3.7 => 5 */
b=(int)(x+y); /* b=6,(int)(6.5) */
c=(int)x;
printf("x=%f,c=%d\n",x,c);
/* x=2.800000,c=2 */
z=(float)d/e; /* z=2.5 */
C语言程序设计 - 第 2章 数据类型、运算符和表达式 60
自增、自减运算符
? 形式
?++i,--i 使用 i之 前,先使 i的值 加 /减 1
?i++,i-- 使用 i之 后,再使 i的值 加 /减 1
? 说明
?++i和 --i的值是加 /减 1之后 i的值
?i++和 i--的值是加 /减 1之前 i的值
?++和 --只能用于变量,不能用于常量和表达式
?++和 --的结合方向是“自右向左”
C语言程序设计 - 第 2章 数据类型、运算符和表达式 61
自增、自减运算符举例
int i=3,j,a,b=1,c=2;
j = ++i; /* i=i+1,j=i,i=4,j=4 */
j = i++; /* j=i,i=i+1,i=5,j=4 */
j = -i++; /* -(i++),i=6,j=-5 */
j = i++*2; /* (i++)*2,i=7,j=12 */
a = (b+c)++; /* 非法 !!! */
a = 34++; /* 非法 !!! */
j = ++i++; /* 非法 !!! */
C语言程序设计 - 第 2章 数据类型、运算符和表达式 62
有关表达式使用的问题
? 表达式中子表达式的求值顺序没有规定
?i=3; j=(i++)+(i++)+(i++);
/* j=9? 12? */
? C编译程序自左向右尽可能多的将若干字
符组合成一个运算符、标识符、关键字
?i+++j /* (i++)+j? i+(++j)? */
? 调用函数时,实参的求值顺序没有规定
?i=3; printf("%d,%d\n",i,i++);
/* 3,3? 4,3? */
C语言程序设计 - 第 2章 数据类型、运算符和表达式 63
赋值运算符 (Assignment Operators)
? 赋值运算符 =
?把右侧表达式的值赋给左侧的变量
?一般情况下,赋值运算符左侧只能是变量
?赋值运算符的优先级较低,“自右向左”结
合
?运算符两侧类型不一致时,要进行类型转换
?注意“赋值”与“等于”的区别,例如
i=i+2;
? 复合赋值运算符
?=前加上算术运算符或位运算符,如 +=,|=
?举例,z*=x+y; /* z=z*(x+y); */
C语言程序设计 - 第 2章 数据类型、运算符和表达式 64
赋值表达式
? 赋值表达式
?<变量 ><赋值运算符 ><表达式 >
?赋值表达式的值就是所赋的值
?运算符右侧的表达式可以是一个赋值表达式
? 举例
?a=5; /*表达式的值为 5*/
?a=b=3; /*a=(b=3)*/
?a=b=c=1; /*a=(b=(c=1))*/
?a=(b=4)+(c=3);/*b=4,c=3,a=7*/
C语言程序设计 - 第 2章 数据类型、运算符和表达式 65
逗号运算符
? 逗号运算符,
?exp1,exp2
?逗号运算符的优先级最低,“自左向右”结
合
?逗号表达式的值是 exp2的值
?exp1和 exp2都可以又是“逗号表达式”
?把多个表达式组合成一个表达式使用
? 举例
?x=(a=3,6*a) /* a=3,x=18 */
?x=a=3,6*a /* a=3,x=3 */
C语言程序设计 - 第 2章 数据类型、运算符和表达式 66
基本输入输出
? 头文件
?#include <stdio.h>
? 输入输出函数
?字符输出函数 putchar
?字符输入函数 getchar
?格式输出函数 printf
?格式输入函数 scanf
?字符串输出函数 puts
?字符串输入函数 gets
C语言程序设计 - 第 2章 数据类型、运算符和表达式 67
字符输出函数 putchar
? 函数说明
?int putchar(int c);
?输出一个字符到标准输出设备
? 参数说明
?int c 要 输出的字符,可以是整数或字符,
若超出字符型范围,则只使用低字节
? 返回值
?若成功,返回输出字符的 ASCII码值
?若失败,返回 EOF (End of File)
C语言程序设计 - 第 2章 数据类型、运算符和表达式 68
函数 putchar举例 (02-01.C)
int c,i;
putchar('a'); /* 输出 'a' */
putchar('\n'); /* 输出换行符 */
putchar(101); /* 输出 'e' */
putchar('\101'); /* 输出 'A' */
c = 1000;
i = putchar(c); /* 输出 'è',i=232 */
C语言程序设计 - 第 2章 数据类型、运算符和表达式 69
字符输入函数 getchar
? 函数说明
?int getchar(void);
?从标准输入设备输入一个字符
?需要输入回车后,函数才返回
? 参数说明
?无参数
? 返回值
?若成功,返回输入字符的 ASCII码值
?若失败,返回 EOF (End of File)
C语言程序设计 - 第 2章 数据类型、运算符和表达式 70
函数 getchar举例 (02-02.C)
int c;
c = getchar(); /* 输入 'a'后回车 */
putchar(c); /* 输出 'a' */
c = getchar(); /* 是否需要输入? */
printf("c=%d\n",c);/* 输出 c=? 10 */
c = getchar(); /* 输入 'abcd'后回车 */
putchar(c); /* 输出 'a' */
putchar(getchar()); /* 输出 'b' */
C语言程序设计 - 第 2章 数据类型、运算符和表达式 71
格式输出函数 printf
? 函数说明
?int printf(char* format[,args...]);
?格式化输出若干任意类型数据
? 参数说明
?char* format 格式控制字符串
?args 需要输出的数据列表,可以多个或没有
? 返回值
?若成功,返回输出的字节数,包括换行符
?若失败,返回 EOF (End of File)
C语言程序设计 - 第 2章 数据类型、运算符和表达式 72
函数 printf的参数说明
? 格式字符串
?包括“格式说明”和“普通字符”
?“格式说明”由 %和“格式字符”组成,将
输出数据按指定格式输出
?“普通字符”按原样输出
? 输出列表
?需要输出的数据
?可以是变量、常量、表达式、函数调用等
?输出数据按顺序与“格式说明”对应输出
C语言程序设计 - 第 2章 数据类型、运算符和表达式 73
函数 printf的格式举例
printf("a=%d b=%d",a,b);
格式说明普通字符 输出列表
输出结果 >a=3 b=4
C语言程序设计 - 第 2章 数据类型、运算符和表达式 74
格式字符
格式字符 说 明
d,i 有符号十进制整数,正数不输出符号
o 无符号八进制整数,不输出前导 0
x,X 无符号十六进制整数,不输出前导 0x或 0X
u 无符号十进制整数
c 转换为无符号字符型,以此为 ASCII码输出一个字符
s 输出字符串,直到遇到 '\0'或达到指定宽度
f 小数形式单、双精度数,缺省精度为 6位小数
e,E 以规范化指数形式输出浮点数,缺省精度为 6位小数
g,G 以 f(F)和 e(E)两种格式中较短的一种输出
% 输出一个 %
C语言程序设计 - 第 2章 数据类型、运算符和表达式 75
附加格式字符
格式字符 说 明
h 有符号或无符号短整型
l 有符号或无符号长整型
L 长双精度型
m 一个正整数,输出数据的最小宽度
n 一个正整数,输出的小数位数或字符串截取个数
,分隔 m和 n
- 输出的数字或字符向左靠齐
+ 输出的数字一直带符号,即正号也输出
0 输出的数字不满规定宽度时,用前导 0填充
? 有符号数字如果没有输出符号,则前面加一个空格
# 八进制和十六进制数加前缀,浮点数格式也有所改变
C语言程序设计 - 第 2章 数据类型、运算符和表达式 76
函数 printf举例 (02-03.C)
int i=1234;
float f=-56.78;
printf("i=%+6d",i);/* "i=?+1234" */
printf("%c",i); /* "ò" */
printf("%#08x",i); /* "0x0004d2" */
printf("%10.5E",f);/* "-5.67800E+01" */
printf("%7.4f%%",f);/* "-56.7800%" */
printf("%+6.3G",f);/* "?-56.8" */
printf("%-6.3s","Hello"); /* "Hel???" */
C语言程序设计 - 第 2章 数据类型、运算符和表达式 77
格式输入函数 scanf
? 函数说明
?int scanf(char* format[,addrs...]);
?格式化输入若干任意类型数据
? 参数说明
?char* format 格式控制字符串
?addrs 需要输入的地址列表,可以有多个
? 返回值
?返回输入并赋值的数据项的个数
C语言程序设计 - 第 2章 数据类型、运算符和表达式 78
函数 scanf使用说明
?,地址列表”中是变量的地址,而非变量
?scanf("%d",&i);
? 关于输入格式
?格式字符串中的普通字符须按相应位置输入
?除字符型 (%c)外,输入项之间用一个或多
个空白字符分隔,包括空格、回车、制表符
?空白字符会作为 %c对应的输入,如果需要
输入下一个非空白字符,可以用 %1s
?如规定了最大宽度,且输入数据超出宽度,
则按宽度截取数据
C语言程序设计 - 第 2章 数据类型、运算符和表达式 79
格式字符
格式字符 说 明
d 有符号十进制整数
i 有符号整数,可以是八进制 (带前导 0)或十六进制
(带前导 0x或 0X)
o 有符号八进制整数,可以带或不带前导 0
x,X 有符号十六进制整数,可以带或不带前导 0x或 0X
u 无符号十进制整数
c 输入一个字符,包括空白字符
s 输入无空白字符的字符串,不需要用 ""括起来
f,e,E,g,G 浮点数,可以用小数形式或指数形式
% 输入一个 %
C语言程序设计 - 第 2章 数据类型、运算符和表达式 80
附加格式字符
格式字符 说 明
h 有符号或无符号短整型
l 有符号或无符号长整型或双精度型
L 长双精度型
m 一个正整数,输入数据的最大宽度
* 需要输入数据,但是在赋值时被跳过
C语言程序设计 - 第 2章 数据类型、运算符和表达式 81
函数 scanf举例 (02-04.C)
int i,j;
char c;
scanf("%d%d",&i,&j);
/* "2 3" or "2<TAB>3" or "2<Enter>3" */
scanf("i=%d,j=%d",&i,&j);
/* "i=2,?j=3" or "i=2,???j=3" */
scanf("%d%c%d",&i,&c,&j);
/* "2 a 3" => i=2,c='?',j出错 */
/* "2a 3" => i=2,c='a',j=3 */
C语言程序设计 - 第 2章 数据类型、运算符和表达式 82
简单的 C程序设计
? 例 1:输入球体半径,求球的体积。
? 例 2:输入大写字母,转换为小写字母。
3
3
4
rV ??
C语言程序设计 - 第 2章 数据类型、运算符和表达式 83
例 1:球体体积 (02-05.C)
#include <stdio.h>
#define PI 3.1415926
void main()
{
float r,V;
printf("r=");
scanf("%f",&r);
V = 4.0 / 3 * PI * r * r * r;
printf("V=%f\n",V);
}
C语言程序设计 - 第 2章 数据类型、运算符和表达式 84
例 2:字母大小写转换 (02-06.C)
#include <stdio.h>
void main()
{
char cup,clow;
cup = getchar();
clow = cup + 'a' - 'A';
printf("%c\n",clow);
}
C语言程序设计 - 第 2章 数据类型、运算符和表达式 85
作 业
习题 3.6,3.9,3.10,3.12(3)~(5)
习题 4.5,4.6,4.9
C语言程序设计 - 第 2章 数据类型、运算符和表达式 86
结束
The End
baixf@ustc.edu.cn
中国科学技术大学电子科学与技术系
Dept,of Elec,Sci,& Tech.,USTC
Fall,2003
第 2章 数据类型、运算符和表达式
C语言程序设计 - 第 2章 数据类型、运算符和表达式 2
目 录
? 数据类型、常量和变量的定义
? 运算符的种类、优先级和结合方向
? 表达式的类型和求值
? 简单的 C程序设计及基本输入输出
C语言程序设计 - 第 2章 数据类型、运算符和表达式 3
C的数据类型 (Data Types)
? 基本类型
?整型、字符型、浮点型(实型)、枚举类型
? 构造类型
?数组类型、结构体类型、共用体类型
? 指针类型
? 空类型
C语言程序设计 - 第 2章 数据类型、运算符和表达式 4
数据类型、常量和变量
? C的数据结构是以数据类型形式出现的
? 由前述数据类型可以构造出更复杂的数
据结构
? C语言的数据有常量和变量之分
? 常量和变量都分别属于某一数据类型
? 程序中用到的所有数据都必须指定类型
? 本章仅介绍基本数据类型
C语言程序设计 - 第 2章 数据类型、运算符和表达式 5
标识符 (Identifier)
? 标识符
?变量名、符号常量名、函数名、类型名 …
? 标识符命名规范
?由字母、数字、下划线 (Underscore,'_')组成
?第一个字符必须为字母或下划线
? C语言标识符是大小写敏感的
?标识符的名称一般应具有一定的含义
?不要与 C语言关键字 (Keywords)重复
?一般不要使用以下划线开头的标识符
C语言程序设计 - 第 2章 数据类型、运算符和表达式 6
标识符示例
? 正确的标识符
?student,num1,_SUM,_1_2_3
?MyName,myname,my_name
? 错误的标识符
?room3-1 包含了其他字符(减号)
?2men 以数字开头
?long 与关键字重复
?Mr.Zhu 包含了其他字符(小数点)
C语言程序设计 - 第 2章 数据类型、运算符和表达式 7
常量 (Constants)
? 常量
?程序运行过程中,其值不能被改变的量
?例如,12,-6.7,'a'…
? 符号常量 (Symbolic Constants)
?用一个标识符代表的常量
?相当于把标识符用一个常量简单替换下来
?标识符是一个整体,不要试图拆开来替换
?含义清楚,一改全改
?习惯上符号常量名用大写字母
C语言程序设计 - 第 2章 数据类型、运算符和表达式 8
常量示例
#define PRICE 30
#define NUM 12
void main()
{
...,..
total = NUM * PRICE;
total2 = 84 * PRICE2;
printf("total=%d",total);
...,..
} 不会被替换
=> total = 12 * 30;
常量
符号常量
C语言程序设计 - 第 2章 数据类型、运算符和表达式 9
变量 (Variables)
? 其值可以改变的量称为变量
? 变量有一个名字,即标识符
? 变量在存储器中占据一定的存储单元
? 变量占据存储空间的大小由其类型决定
? 变量名表示存储变量的存储单元地址
? 程序使用变量名表示这个变量所占据的
存储单元里 存储的数据的值
? 变量要“先定义,后使用”
C语言程序设计 - 第 2章 数据类型、运算符和表达式 10
变量的存储
34
a 变量名
存储单元 (地址 )
变量值
C语言程序设计 - 第 2章 数据类型、运算符和表达式 11
整型 (Integer)
? 整型常量的表示方法
? 整型变量
?整型数据在内存中的存放形式
?整型变量的类型
?整型变量的定义
?整型数据的溢出
? 整型常量的类型
C语言程序设计 - 第 2章 数据类型、运算符和表达式 12
整型常量的表示方法
? 十进制 (Decimal)
?例如,123,-456,0
? 八进制 (Octal)
?以 0开头,不得含有 8或 9
?例如,0123,-0456
?错例,0138,-0912
? 十六进制 (Hexadecimal)
?以 0x或 0X开头,用 a~f或 A~F表示 10~15
?例如,0x123,-0X45,0x3AB,-0xabc
C语言程序设计 - 第 2章 数据类型、运算符和表达式 13
整型数据在内存中的存放方式
? 二进制形式
?举例,int i=50; /*int类型占 2字节 */
? 补码 (Complement)
?正数:与原码一致,首位为 0
?负数:绝对值取反加一,首位为 1
?零:各位全为 0
0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 0
高地址字节 低地址字节
C语言程序设计 - 第 2章 数据类型、运算符和表达式 14
补码举例
? 举例
?int i=-50; /*int类型占 2字节 */
0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 0
1 1 1 1 1 1 1 1 1 1 0 0 1 1 0 1
1 1 1 1 1 1 1 1 1 1 0 0 1 1 1 0
50的原码
-50的补码
取反
加一
C语言程序设计 - 第 2章 数据类型、运算符和表达式 15
整型变量的分类
? 按占用存储空间的大小划分
?基本整型 int
?短整型 short [int]
?长整型 long [int]
? 按有无符号划分
?有符号 [signed]
?无符号 unsigned
? 上述两种分类方式组合,可得到 6种类型
C语言程序设计 - 第 2章 数据类型、运算符和表达式 16
整数的长度
? 整数的类型与长度
?short:占 2字节( 16bit)
?long,占 4字节( 32bit)
?int,占 2或 4字节( 16或 32bit)
? 2Bytes = short ≤ int ≤ long = 4Bytes
?若需要精确的长度,可选用 short或 long
? 举例
? BC3.1:int长度为 2Bytes
? gcc,int长度为 4Bytes
C语言程序设计 - 第 2章 数据类型、运算符和表达式 17
有符号数与无符号数
? 有符号数
?二进制补码表示,首位为符号位
?指定 signed或缺省情况,即为有符号数
? 无符号数
?没有符号位,只能表示非负数
?无符号数类型必须指定为 unsigned
?若把负数赋值给无符号数,则把该负数的补
码当作无符号数进行处理
C语言程序设计 - 第 2章 数据类型、运算符和表达式 18
有符号数与无符号数举例
void main()
{
int i;
unsigned j;
i=j=-50;
i=i/2; /*-25*/
j=j/2; /*32743*/
}
1 1 1 1 1 1 1 1 1 1 0 0 1 1 1 0
-50的补码 i,j
/ 2
1 1 1 1 1 1 1 1 1 1 1 0 0 1 1 1
0 1 1 1 1 1 1 1 1 1 1 0 0 1 1 1
i/2-25的补码
j/232743的补码 /原码
C语言程序设计 - 第 2章 数据类型、运算符和表达式 19
整型数据的取值范围
类 型 长度 (bit) 取值范围
[signed] short [int] 16 -215 ~ 215-1
unsigned short [int] 16 0 ~ 216-1
[signed] int 16 or 32 -215(31) ~ 215(31)-1
unsigned [int] 16 or 32 0 ~ 216(32)-1
[signed] long [int] 32 -231 ~ 231-1
unsigned long [int] 32 0 ~ 232-1
C语言程序设计 - 第 2章 数据类型、运算符和表达式 20
整型变量的定义 (Definition)
? 定义形式
?int a,b;
?unsigned c;
?long d;
?unsigned short e;
? 变量的定义一般放在一个函数开头的声
明部分,关于变量定义的具体内容在以
后相关章节里详细介绍
C语言程序设计 - 第 2章 数据类型、运算符和表达式 21
整型变量的定义与使用举例
void main()
{
int a; /*定义有符号基本整型变量 a*/
unsigned b;/*定义无符号基本整型变量 b*/
long c; /*定义有符号长整型变量 c*/
a = -23; /*a的值为 -23*/
b = 45; /*b的值为 45*/
c = a + b; /*c的值为 22*/
}
C语言程序设计 - 第 2章 数据类型、运算符和表达式 22
整型数据的溢出 (Overflow)
? 溢出
?数据超出了变量能够存储的范围,造成数据
丢失或数值改变等
? 举例
void main()
{
int a = 32767;
a++; /*32768?*/
}
0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+1
32767的补码
-32768的补码
C语言程序设计 - 第 2章 数据类型、运算符和表达式 23
整型常量的类型
? 常量的类型后缀 (Suffix)
?l,L 表示常量是一个长整型
?u,U 表示常量是一个无符号整型数
?两种后缀可以一起使用
? 举例
?123l 长整型常数 123
?456U 无符号整型常数 456
?789ul无符号长整型常数 789
?101Lu无符号长整型常数 101
C语言程序设计 - 第 2章 数据类型、运算符和表达式 24
整型常量使用中的类型问题
? 对整型变量赋值
?常量的值不要超过变量的取值范围
? 直接使用常量
?带有 l,L,u,U等后缀的整型常量一般用
于函数调用
?不带有后缀的整型常量的类型,是根据其数
值大小所处的范围来确定的
C语言程序设计 - 第 2章 数据类型、运算符和表达式 25
浮点型 (Floating Point)
? 浮点型常量的表示方法
? 浮点型变量
?浮点型数据在内存中的存放形式
?浮点型变量的类型
?浮点型数据的舍入误差
? 浮点型常数的类型
C语言程序设计 - 第 2章 数据类型、运算符和表达式 26
浮点型常量的表示方法
? 十进制小数形式
?由符号、数字和小数点 (必须 )组成
?整数和小数部分都可省略,但不能同时省略
?举例,12.3,-.123,123.,0.,.0
? 指数形式
?由整数 (或小数 ),e(或 E)、整数顺序组成
?e或 E之前必须有数字,之后必须是整数
?举例,123.4e-5表示 123.4× 10-5
?错例,e1,12e,1.2e3.4,.e5,e
C语言程序设计 - 第 2章 数据类型、运算符和表达式 27
规范化指数形式
? 规范化指数形式
?类似于“科学计数法”
?e或 E之前的小数中,小数点前面有且仅有一
个非零数字
? 举例,123.456
?规范化形式,1.23456e2,1.23456E+002
?非规范化形式,123.456,12.3456e1、
12345.6e-2,0.123456e3、
12345600e-5…
C语言程序设计 - 第 2章 数据类型、运算符和表达式 28
浮点型数据在内存中的存放方式
? 二进制规范化指数形式
? 小数部分长度与能表示的精度有关
? 指数部分长度与能表示的数值范围有关
1 1 0 1 1 0 0 1 1 0 1 1 0 0 1 0
指数部分 e 小数部分 f符号 s
es fv 2).1()1( ???
C语言程序设计 - 第 2章 数据类型、运算符和表达式 29
几个特殊的数
? 无穷大 (Infinition)
?Inf 举例,1.0/0.0
?-Inf 举例,-1.0/0.0
? NaN (Not a Number)
?NaN 举例,sqrt(-1) /*开平方 */
?-NaN 举例,-sqrt(-1)
? 零 (Zero)
?浮点数用特殊的形式表示零
C语言程序设计 - 第 2章 数据类型、运算符和表达式 30
浮点型变量的类型
? 分类
?单精度 float
?双精度 double
?长双精度 long double
? 长度和取值范围
类 型 长度 (bit) 有效数字 绝对值范围
float 32 6~7 10-37~1038
double 64 15~16 10-307~10308
long double 128 18~19 10-4931~104932
C语言程序设计 - 第 2章 数据类型、运算符和表达式 31
浮点型数据的舍入误差
? 由于浮点型变量能够表示的有效数字有
限,将有效位以外的数字舍去造成误差
? 举例
float a=123456.789e5,b;
b = a + 20; /*b=12345678920?*/
printf("a=%f\nb=%f\n",a,b);
运行结果 > a=12345678848.000000
b=12345678848.000000
?思考,1.0/3*3=?
C语言程序设计 - 第 2章 数据类型、运算符和表达式 32
浮点型常量的类型
? 类型后缀
?f,F 表示常量是一个单精度型浮点数
?l,L 表示常量是一个长双精度型浮点数
?无任何后缀的浮点型常量视作双精度型
? 对浮点型变量赋值
?一个浮点型常量可以赋值给任何类型的浮点
型变量
?根据变量类型截取常量的相应有效数字
?注意防止出现溢出
C语言程序设计 - 第 2章 数据类型、运算符和表达式 33
字符型 (Character)
? 字符型常量
? 字符型变量
? 字符型数据在内存中的存放形式
? 字符型数据的使用方法
? 字符串常量
C语言程序设计 - 第 2章 数据类型、运算符和表达式 34
字符型常量
? 单引号括起来的 一个 字符
?举例,'a','A','1','?','?'…
?错例,'abc','','我 '…
? 转义字符
?以 '\'开头的特殊字符
?'\ddd' 1到 3位 8进制数 ASCII码代表的字符
?'\xhh' 1到 2位 16进制数 ASCII码代表的字符
?举例,'\n','\t','\\','\'','\"'、
'\123','\x3A'…
C语言程序设计 - 第 2章 数据类型、运算符和表达式 35
字符型变量
? 字符型变量只能存放 一个 字符
? 定义与使用
void main()
{
char c1,c2; /*定义字符型变量 c1和 c2*/
c1 = 'a'; /*c1的值为 'a'*/
c2 = '2'; /*c2的值为 '2'*/
}
C语言程序设计 - 第 2章 数据类型、运算符和表达式 36
字符型数据在内存中的存放形式
? 一个字符型数据占一个字节的空间
? 字符型数据以其 ASCII码形式存放
? 字符型数据的存放形式与只占一个字节
长度的整型数据完全相同
01100001
c1='a'
(ASCII=97)
00110010
c1='2'
(ASCII=50)
C语言程序设计 - 第 2章 数据类型、运算符和表达式 37
字符型数据的使用方法
? 可以把字符型数据视作一种长度为 1字节
的整型数据处理
?当使用字符型数据时,与使用这个字符的
ASCII码 (一个 8位整数 )是完全一样的
?字符型数据的用法与整型数据完全一样,包
括运算、赋值、输入、输出等
?字符型数据使用过程中,同样需要注意溢出、
符号等问题
? 是字符还是整数,只有在输出时才有意义
C语言程序设计 - 第 2章 数据类型、运算符和表达式 38
字符型数据使用举例
void main()
{
char c;
int i,j;
c = 97; /*c = 'a'*/
i = c + 20;/*i = 117*/
j = '2'; /*j = 50*/
printf("%c,%d\n",c,c); /*a,97*/
}
C语言程序设计 - 第 2章 数据类型、运算符和表达式 39
字符型变量的符号
? 字符型变量与整型变量一样,也分为有
符号数与无符号数
? 无符号字符
?unsigned char c;
?举例,表示一个班级的人数 (<256)
? 赋值和使用中需要注意的问题,与整型
变量相同
C语言程序设计 - 第 2章 数据类型、运算符和表达式 40
字符串 (String)常量
? 表示形式
?一对双引号括起来的字符序列
?引号内可以包括 0个,1个或多个字符
?字符序列中的特殊字符用转义字符表示
?举例,"abc","a","","?","我 "
?举例,"12.4","$#*!","C:\\HOME"
? 字符常量和字符串常量是不同类型的数据
?例如,'a'与 "a"是不同的
?不能把一个字符串赋值给一个字符型变量
C语言程序设计 - 第 2章 数据类型、运算符和表达式 41
字符串在内存中的存放方式
? 在内存中每个字符按顺序存放
? 字符串结尾有一个 空字符 (ASCII=0,'\0')
作为字符串结束标志
? 字符串结束标志 '\0'是不能显示的,在
字符串常量中,也不用显式写出来
? 举例
?"TEST"
?""
?"a"
'T''E''S' 'T' \0 84 69 83 84 00
\0
'a' \0
00
97 00
C语言程序设计 - 第 2章 数据类型、运算符和表达式 42
变量赋初值 (Initialization)
? 在定义变量的同时对变量赋值 (初始化 )
? 举例
?int a=1;
/*相当于 int a; a=1;*/
?int a,b=3;
/*对 b赋初值,a没有初值 */
?int b,c,a=b=c=100;
/*对三个变量赋同样的初值 */
? 变量使用前,一般应先对它赋值
C语言程序设计 - 第 2章 数据类型、运算符和表达式 43
各类数值型数据间的混合运算
? 整型、字符型、浮点型数据可混合运算
? 混合运算时,不同类型的数据按照一定
的规则先转换为同一类型,然后再运算
double
long
unsigned
int
float
char,short
高
低
C语言程序设计 - 第 2章 数据类型、运算符和表达式 44
运算符 (Operator)
? 运算符的种类
? 运算符的优先级
? 运算符的结合方向
C语言程序设计 - 第 2章 数据类型、运算符和表达式 45
运算符的种类 (1)
? 算术运算符 + - * / % ++ --
? 关系运算符 > < == >= <= !=
? 逻辑运算符 ! && ||
? 位运算符 << >> ~ | ^ &
? 赋值运算符 = += -= *= /= %=
>>= <<= &= ^= |=
? 条件运算符?:
C语言程序设计 - 第 2章 数据类型、运算符和表达式 46
运算符的种类 (2)
? 逗号运算符,
? 指针运算符 * &
? 求字节数运算符 sizeof
? 强制类型转换运算符 (type)
? 分量运算符, ->
? 下标运算符 []
? 其他运算符 ()
C语言程序设计 - 第 2章 数据类型、运算符和表达式 47
运算符的优先级 (Precedence)
? 优先级
?运算符的运算次序按优先级由高到低执行
?可以用圆括号 ( )改变运算符的执行次序
? 举例
?a+b*c–d/e
/*先算乘除,后算加减 */
/*乘除比加减优先级高 */
?(a+b)*(c-d)/e
/*先算加减,后算乘除 */
C语言程序设计 - 第 2章 数据类型、运算符和表达式 48
运算符的结合方向 (Associativity)
? 结合方向
?当一个操作数两侧的运算符优先级相同时,
运算次序按照结合方向的规定进行
? 举例
?a+b-c
/*+和 -的结合方向都是从左向右 */
/*b先与 +结合计算 a+b,然后执行减法 */
?a=b=1
/*=的结合方向是从右向左,先计算 b=1*/
C语言程序设计 - 第 2章 数据类型、运算符和表达式 49
运算符的结合方向规则
? 单目运算符的结合方向都是“从右向左”
?!,~,++,--,+(正号 ),-(负号 )
?*(指针运算符 ),&(地址运算符 )
?sizeof,(type)
? 赋值运算符的结合方向是“从右向左”
? 三目运算符的结合方向是“从右向左”
?唯一的三目运算符:条件运算符?:
? 其他运算符的结合方向都是“从左向右”
C语言程序设计 - 第 2章 数据类型、运算符和表达式 50
优先级与结合方向总结
? 不同优先级的运算符,运算次序按优先
级由高到低执行
? 同一优先级的运算符,运算次序按结合
方向的规定执行
? 可以使用圆括号 ( )明确运算次序
?圆括号 ()具有最高的优先级
C语言程序设计 - 第 2章 数据类型、运算符和表达式 51
表达式 (Expression)
? 表达式的概念
? 表达式的类型
? 表达式求值
?算术运算符和算术表达式
?赋值运算符和赋值表达式
?逗号运算符和逗号表达式
C语言程序设计 - 第 2章 数据类型、运算符和表达式 52
表达式的概念
? 表达式
?用运算符把操作数连接起来,并符合 C语言
语法规则的式子
?操作数包括常量、变量、函数调用、表达式
?广义上,常量、变量、函数调用也可以看作
属于表达式的范畴
? 举例
?a+2.5*b-6/c+'z'-max(x,y)
?!((a<1e-6)&&(b==(c+sqrt(f))))
C语言程序设计 - 第 2章 数据类型、运算符和表达式 53
表达式的类型
? 表达式的类型
?表达式的值的类型
?取决于操作数的类型以及它们所做的运算
? 举例
?a+2.5*b-6/c+'z'
/*混合类型算术运算,值为 double类型 */
?!((a<1e-6)&&(b==(c+sqrt(f))))
/*逻辑判断的结果是逻辑值 */
/*C语言用整型表示逻辑类型 */
C语言程序设计 - 第 2章 数据类型、运算符和表达式 54
算术运算符 (Arithmetic Operators)
? 基本算术运算符
?+ - * / %
? 强制类型转换运算符
?(类型名 )
? 自增、自减运算符
?++ --
C语言程序设计 - 第 2章 数据类型、运算符和表达式 55
基本算术运算符
运算符 名称 举例 说明
+ 正值运算符 (正号 ) +b 值不变
- 负值运算符 (负号 ) -d 取相反数
+ 加法运算符 a+3 加法
- 减法运算符 c-4 减法
* 乘法运算符 a*3 乘法
/ 除法运算符 c/d 除法
% 模运算符 e%4 求余数、取模
C语言程序设计 - 第 2章 数据类型、运算符和表达式 56
基本算术运算符的特性
? 优先级 (从高到低 )
?+ (正号 ) – (负号 )
?* / %
?+ (加 ) – (减 )
? 结合方向
?+ (正号 ) – (负号 ):从右向左
?+ (加 ) – (减 ) * / %,从左向右
C语言程序设计 - 第 2章 数据类型、运算符和表达式 57
基本算术运算符的说明
? 两个整数相除,结果也为整数
?直接舍去商的小数部分,而不会“四舍五入”
?负数整数除法,结果的舍入方向没有规定
?如果需要得到精确的运算结果,可以把其中
一个操作数转换为浮点数
?举例,5/3(=1),5.0/3(=1.66666…)
?举例,-5/3(=-1?-2?)
? 模运算符的两个操作数都必须是整数
?负数模运算结果的符号没有规定
?举例,5%3(=2),-5%3(=-2?1?)
C语言程序设计 - 第 2章 数据类型、运算符和表达式 58
强制类型转换运算符
? 形式
?(类型名 )操作数
? 说明
?强制把表达式转换成所需的类型
?强制类型转换运算符的优先级比较高
?强制类型转换不会改变操作数自身的类型,
只是得到一个所需类型的中间量
?多用于自动类型转换不能实现的目的
?强制类型转换后,会影响 C语言做类型检查
C语言程序设计 - 第 2章 数据类型、运算符和表达式 59
强制类型转换举例
float x=2.8,y=3.7,z;
int a,b,c,d=5,e=2;
a=(int)x+y; /* a=5,2+3.7 => 5 */
b=(int)(x+y); /* b=6,(int)(6.5) */
c=(int)x;
printf("x=%f,c=%d\n",x,c);
/* x=2.800000,c=2 */
z=(float)d/e; /* z=2.5 */
C语言程序设计 - 第 2章 数据类型、运算符和表达式 60
自增、自减运算符
? 形式
?++i,--i 使用 i之 前,先使 i的值 加 /减 1
?i++,i-- 使用 i之 后,再使 i的值 加 /减 1
? 说明
?++i和 --i的值是加 /减 1之后 i的值
?i++和 i--的值是加 /减 1之前 i的值
?++和 --只能用于变量,不能用于常量和表达式
?++和 --的结合方向是“自右向左”
C语言程序设计 - 第 2章 数据类型、运算符和表达式 61
自增、自减运算符举例
int i=3,j,a,b=1,c=2;
j = ++i; /* i=i+1,j=i,i=4,j=4 */
j = i++; /* j=i,i=i+1,i=5,j=4 */
j = -i++; /* -(i++),i=6,j=-5 */
j = i++*2; /* (i++)*2,i=7,j=12 */
a = (b+c)++; /* 非法 !!! */
a = 34++; /* 非法 !!! */
j = ++i++; /* 非法 !!! */
C语言程序设计 - 第 2章 数据类型、运算符和表达式 62
有关表达式使用的问题
? 表达式中子表达式的求值顺序没有规定
?i=3; j=(i++)+(i++)+(i++);
/* j=9? 12? */
? C编译程序自左向右尽可能多的将若干字
符组合成一个运算符、标识符、关键字
?i+++j /* (i++)+j? i+(++j)? */
? 调用函数时,实参的求值顺序没有规定
?i=3; printf("%d,%d\n",i,i++);
/* 3,3? 4,3? */
C语言程序设计 - 第 2章 数据类型、运算符和表达式 63
赋值运算符 (Assignment Operators)
? 赋值运算符 =
?把右侧表达式的值赋给左侧的变量
?一般情况下,赋值运算符左侧只能是变量
?赋值运算符的优先级较低,“自右向左”结
合
?运算符两侧类型不一致时,要进行类型转换
?注意“赋值”与“等于”的区别,例如
i=i+2;
? 复合赋值运算符
?=前加上算术运算符或位运算符,如 +=,|=
?举例,z*=x+y; /* z=z*(x+y); */
C语言程序设计 - 第 2章 数据类型、运算符和表达式 64
赋值表达式
? 赋值表达式
?<变量 ><赋值运算符 ><表达式 >
?赋值表达式的值就是所赋的值
?运算符右侧的表达式可以是一个赋值表达式
? 举例
?a=5; /*表达式的值为 5*/
?a=b=3; /*a=(b=3)*/
?a=b=c=1; /*a=(b=(c=1))*/
?a=(b=4)+(c=3);/*b=4,c=3,a=7*/
C语言程序设计 - 第 2章 数据类型、运算符和表达式 65
逗号运算符
? 逗号运算符,
?exp1,exp2
?逗号运算符的优先级最低,“自左向右”结
合
?逗号表达式的值是 exp2的值
?exp1和 exp2都可以又是“逗号表达式”
?把多个表达式组合成一个表达式使用
? 举例
?x=(a=3,6*a) /* a=3,x=18 */
?x=a=3,6*a /* a=3,x=3 */
C语言程序设计 - 第 2章 数据类型、运算符和表达式 66
基本输入输出
? 头文件
?#include <stdio.h>
? 输入输出函数
?字符输出函数 putchar
?字符输入函数 getchar
?格式输出函数 printf
?格式输入函数 scanf
?字符串输出函数 puts
?字符串输入函数 gets
C语言程序设计 - 第 2章 数据类型、运算符和表达式 67
字符输出函数 putchar
? 函数说明
?int putchar(int c);
?输出一个字符到标准输出设备
? 参数说明
?int c 要 输出的字符,可以是整数或字符,
若超出字符型范围,则只使用低字节
? 返回值
?若成功,返回输出字符的 ASCII码值
?若失败,返回 EOF (End of File)
C语言程序设计 - 第 2章 数据类型、运算符和表达式 68
函数 putchar举例 (02-01.C)
int c,i;
putchar('a'); /* 输出 'a' */
putchar('\n'); /* 输出换行符 */
putchar(101); /* 输出 'e' */
putchar('\101'); /* 输出 'A' */
c = 1000;
i = putchar(c); /* 输出 'è',i=232 */
C语言程序设计 - 第 2章 数据类型、运算符和表达式 69
字符输入函数 getchar
? 函数说明
?int getchar(void);
?从标准输入设备输入一个字符
?需要输入回车后,函数才返回
? 参数说明
?无参数
? 返回值
?若成功,返回输入字符的 ASCII码值
?若失败,返回 EOF (End of File)
C语言程序设计 - 第 2章 数据类型、运算符和表达式 70
函数 getchar举例 (02-02.C)
int c;
c = getchar(); /* 输入 'a'后回车 */
putchar(c); /* 输出 'a' */
c = getchar(); /* 是否需要输入? */
printf("c=%d\n",c);/* 输出 c=? 10 */
c = getchar(); /* 输入 'abcd'后回车 */
putchar(c); /* 输出 'a' */
putchar(getchar()); /* 输出 'b' */
C语言程序设计 - 第 2章 数据类型、运算符和表达式 71
格式输出函数 printf
? 函数说明
?int printf(char* format[,args...]);
?格式化输出若干任意类型数据
? 参数说明
?char* format 格式控制字符串
?args 需要输出的数据列表,可以多个或没有
? 返回值
?若成功,返回输出的字节数,包括换行符
?若失败,返回 EOF (End of File)
C语言程序设计 - 第 2章 数据类型、运算符和表达式 72
函数 printf的参数说明
? 格式字符串
?包括“格式说明”和“普通字符”
?“格式说明”由 %和“格式字符”组成,将
输出数据按指定格式输出
?“普通字符”按原样输出
? 输出列表
?需要输出的数据
?可以是变量、常量、表达式、函数调用等
?输出数据按顺序与“格式说明”对应输出
C语言程序设计 - 第 2章 数据类型、运算符和表达式 73
函数 printf的格式举例
printf("a=%d b=%d",a,b);
格式说明普通字符 输出列表
输出结果 >a=3 b=4
C语言程序设计 - 第 2章 数据类型、运算符和表达式 74
格式字符
格式字符 说 明
d,i 有符号十进制整数,正数不输出符号
o 无符号八进制整数,不输出前导 0
x,X 无符号十六进制整数,不输出前导 0x或 0X
u 无符号十进制整数
c 转换为无符号字符型,以此为 ASCII码输出一个字符
s 输出字符串,直到遇到 '\0'或达到指定宽度
f 小数形式单、双精度数,缺省精度为 6位小数
e,E 以规范化指数形式输出浮点数,缺省精度为 6位小数
g,G 以 f(F)和 e(E)两种格式中较短的一种输出
% 输出一个 %
C语言程序设计 - 第 2章 数据类型、运算符和表达式 75
附加格式字符
格式字符 说 明
h 有符号或无符号短整型
l 有符号或无符号长整型
L 长双精度型
m 一个正整数,输出数据的最小宽度
n 一个正整数,输出的小数位数或字符串截取个数
,分隔 m和 n
- 输出的数字或字符向左靠齐
+ 输出的数字一直带符号,即正号也输出
0 输出的数字不满规定宽度时,用前导 0填充
? 有符号数字如果没有输出符号,则前面加一个空格
# 八进制和十六进制数加前缀,浮点数格式也有所改变
C语言程序设计 - 第 2章 数据类型、运算符和表达式 76
函数 printf举例 (02-03.C)
int i=1234;
float f=-56.78;
printf("i=%+6d",i);/* "i=?+1234" */
printf("%c",i); /* "ò" */
printf("%#08x",i); /* "0x0004d2" */
printf("%10.5E",f);/* "-5.67800E+01" */
printf("%7.4f%%",f);/* "-56.7800%" */
printf("%+6.3G",f);/* "?-56.8" */
printf("%-6.3s","Hello"); /* "Hel???" */
C语言程序设计 - 第 2章 数据类型、运算符和表达式 77
格式输入函数 scanf
? 函数说明
?int scanf(char* format[,addrs...]);
?格式化输入若干任意类型数据
? 参数说明
?char* format 格式控制字符串
?addrs 需要输入的地址列表,可以有多个
? 返回值
?返回输入并赋值的数据项的个数
C语言程序设计 - 第 2章 数据类型、运算符和表达式 78
函数 scanf使用说明
?,地址列表”中是变量的地址,而非变量
?scanf("%d",&i);
? 关于输入格式
?格式字符串中的普通字符须按相应位置输入
?除字符型 (%c)外,输入项之间用一个或多
个空白字符分隔,包括空格、回车、制表符
?空白字符会作为 %c对应的输入,如果需要
输入下一个非空白字符,可以用 %1s
?如规定了最大宽度,且输入数据超出宽度,
则按宽度截取数据
C语言程序设计 - 第 2章 数据类型、运算符和表达式 79
格式字符
格式字符 说 明
d 有符号十进制整数
i 有符号整数,可以是八进制 (带前导 0)或十六进制
(带前导 0x或 0X)
o 有符号八进制整数,可以带或不带前导 0
x,X 有符号十六进制整数,可以带或不带前导 0x或 0X
u 无符号十进制整数
c 输入一个字符,包括空白字符
s 输入无空白字符的字符串,不需要用 ""括起来
f,e,E,g,G 浮点数,可以用小数形式或指数形式
% 输入一个 %
C语言程序设计 - 第 2章 数据类型、运算符和表达式 80
附加格式字符
格式字符 说 明
h 有符号或无符号短整型
l 有符号或无符号长整型或双精度型
L 长双精度型
m 一个正整数,输入数据的最大宽度
* 需要输入数据,但是在赋值时被跳过
C语言程序设计 - 第 2章 数据类型、运算符和表达式 81
函数 scanf举例 (02-04.C)
int i,j;
char c;
scanf("%d%d",&i,&j);
/* "2 3" or "2<TAB>3" or "2<Enter>3" */
scanf("i=%d,j=%d",&i,&j);
/* "i=2,?j=3" or "i=2,???j=3" */
scanf("%d%c%d",&i,&c,&j);
/* "2 a 3" => i=2,c='?',j出错 */
/* "2a 3" => i=2,c='a',j=3 */
C语言程序设计 - 第 2章 数据类型、运算符和表达式 82
简单的 C程序设计
? 例 1:输入球体半径,求球的体积。
? 例 2:输入大写字母,转换为小写字母。
3
3
4
rV ??
C语言程序设计 - 第 2章 数据类型、运算符和表达式 83
例 1:球体体积 (02-05.C)
#include <stdio.h>
#define PI 3.1415926
void main()
{
float r,V;
printf("r=");
scanf("%f",&r);
V = 4.0 / 3 * PI * r * r * r;
printf("V=%f\n",V);
}
C语言程序设计 - 第 2章 数据类型、运算符和表达式 84
例 2:字母大小写转换 (02-06.C)
#include <stdio.h>
void main()
{
char cup,clow;
cup = getchar();
clow = cup + 'a' - 'A';
printf("%c\n",clow);
}
C语言程序设计 - 第 2章 数据类型、运算符和表达式 85
作 业
习题 3.6,3.9,3.10,3.12(3)~(5)
习题 4.5,4.6,4.9
C语言程序设计 - 第 2章 数据类型、运算符和表达式 86
结束
The End