第 2章 数据类型、运算符与表达式
2.1 程序设计概述
2.2 C语言的数据类型
2.3 常量和变量
2.4 整型数据
2.5 实型数据
2.6 字符型数据
2.7 算术运算与算术表达式
2.8 赋值运算与赋值表达式
2.9 C语言特有的运算和运算符
[Return]
2.1 程序设计概述
一个程序应包括对数据的描述和对数据处理的描述。
1.对数据的描述,即数据结构。数据结构是计算机学
科的核心课程之一,有许多专门著作论述,本课程就不再
赘述。
在 C语言中,系统提供的数据结构,是以数据类型的形
式出现的。
2.对数据处理的描述,即计算机算法。算法是为解决
一个问题而采取的方法和步骤,是程序的灵魂。为此,著
名计算机科学家沃思( Nikiklaus Wirth)提出一个公式:
数据结构 + 算法 = 程序
实际上,一个程序除了数据结构和算法外,还必须使
用一种计算机语言,并采用结构化方法来表示。
[Return]
2.2 C语言的数据类型
C语言提供的数据结构, 是以数据类型形式出现的 。 具体
分类如下:
1.基本类型
分为整型, 实型 ( 又称浮点型 ), 字符型和枚举型四种 。
2.构造类型
分为数组类型, 结构类型和共用类型三种 。
3.指针类型 。 在第 9章中介绍 。
4.空类型
C语言中的数据, 有常量和变量之分, 它们分别属于上述
这些类型 。
本章将介绍基本类型中的整型, 实型和字符型三种数据 。
[Return]
2.3 常量和变量
2.3.1 常量
1.常量的概念
在程序运行过程中,其值不能被改变的量称为常量。
2.常量的分类
( 1)整型常量
( 2)实型常量
( 3)字符常量。
( 4)符号常量。
常量的类型,可通过书写形式来判别。
2.3.2 变量
1.变量的概念
在程序运行过程中, 其值可以被改变的量称为变量 。
2.变量的两个要素
( 1) 变量名 。 每个变量都必须有一个名字 ──变量名,
变量命名遵循标识符命名规则 。
( 2) 变量值 。 在程序运行过程中, 变量值存储在内
存中 。 在程序中, 通过变量名来引用变量的值 。
3,标识符命名规则
( 1) 有效字符:只能由字母, 数字和下划线组成,
且以字母或下划线开头 。
( 2) 有效长度:随系统而异, 但至少前8个字符有
效 。 如果超长, 则超长部分被舍弃 。
例如, 由于 student_name和 student_number的前8个字
符相同, 有的系统认为这两个变量, 是一回事而不加区
别 。
在 TC V2.0中, 变量名 ( 标识符 ) 的有效长度为1~
32个字符, 缺省值为32 。
( 3) C语言的关键字不能用作变量名 。
注意, 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;
[Return]
2.4 整型数据
2.4.1 整型变量
1.分类
根据占用内存字节数的不同,整型变量又分为4类:
( 1)基本整型(类型关键字为 int)。
( 2)短整型(类型关键字为 short [int])。
( 3)长整型(类型关键字为 long [int])。
( 4)无符号整型。无符号型又分为无符号基本整型
( unsigned [int])、无符号短整型( unsigned short)和无符
号长整型( unsigned long)三种,只能用来存储无符号整数。
2.占用内存字节数与值域
上述各类型整型变量占用的内存字节数,随系统而异。
在 16位操作系统中,一般用2字节表示一个 int型变量,且
long型(4字节) ≥int型(2字节) ≥short型(2字节)。
显然,不同类型的整型变量,其值域不同。占用内存字
节数为 n的(有符号)整型变量,其值域为,-2n*8-1~( 2n*8-1-
1);无符号整型变量的值域为,0~( 2n*8-1)。
例如,PC机中的一个 int型变量,其值域为 -22*8-1~( 22*8-1-
1),即 -32768~32767;一个 unsigned型变量的值域为,0~
( 22*8-1),即 0~65535。
2.4.2 整型常量
1,三种表示形式
整型常量即整常数, 在C语言中可用三种形式表示:
( 1) 十进制 。 例如 10,36。
( 2) 八进制 ( 以数字0开头 ) 。 例如 012。
( 3) 十六进制 ( 以数字0 +小写字母 x开头 ) 。 例如 0x36。
2,分类
( 1) 基本整型 。 在 16位机中, 用 2字节存储, 其数据范
围与 int型变量一样 。
( 2) 长整型 ( 在数值后面加, L( l), ) 。 对超出基
本整型值域的整型常量, 可使用长整型常量表示, 其取值
范围可达 -2 31 -( 2 31 -1 ) 。 例如, 123l,315L等 。
3,类型匹配规则
类型匹配规则为:一个整型常量, 可以赋给能容纳下其
值的整型变量 。
例如, 其值在 -2 15 --( 2 15 -1 ) 的整型常量, 可以赋
给 int型变量和 long int型变量;其值在 -2 31 --( 2 31 -1 )
的整型常量, 就只能赋给 long int型变量 。
注意,常量无 unsigned型 。 但一个非负整型常量, 只要
它的值不超过相应变量的值域 ( 即取值范围 ), 也可以赋
给 unsigned型变量 。
[Return]
2.5 实型数据
2.5.1 实型变量
C语言的实型变量,分为两种:
( 1)单精度型。类型关键字为 float,一般占4字节(32位)、提
供7位有效数字。
( 2)双精度型。类型关键字为 double,一般占8个字节、提供
15~16位有效数字。
2.5.2 实型常量
1,表示形式
实型常量即实数,在C语言中又称浮点数,其值有两种表达形式:
( 1)十进制形式。例如 3.14,9.8。
( 2)指数形式,<尾数 >E( e) <整型指数 >。例如 3.0E +5等。
2,关于类型
实型常量不分 float型和 double型。一个实型常量,可以赋给一个
实型变量( float型或 double型)。
[Return]
2.6 字符型数据
2.6.1 字符常量
1.字符常量的定义
用一对单引号括起来的单个字符,称为字符常量。
例如,‘ A?、‘1’、‘+’等。
2.转义字符
C语言还允许使用一种特殊形式的字符常量,就是以
反斜杠,\,开头的转义字符。
注意,如果反斜杠或单引号本身作为字符常量,必须
使用转义字符:‘ \\?、‘ \??。
[案例 2.1] 用转义字符输出可打印字符和不可打印字符。
/*案例代码文件名,AL2_1.C*/
/*程序功能:用转义字符输出可打印字符和不可打印
字符 */
main()
{ printf(“\x4F\x4B\x21\n”); /* 等价于 printf(“OK!\n”); */
printf(“\x15 \xAB\n”);
}
程序运行结果如下:
OK!
§ ? [程序演示 ]
2.6.2 字符变量
字符变量的类型关键字为 char,一般占用 1字节内存单元。
1.变量值的存储
字符变量用来存储字符常量。将一个字符常量存储到一
个字符变量中,实际上是将该字符的 ASCII码值(无符号整
数)存储到内存单元中。
例如,
char ch1,ch2; /*定义两个字符变量,ch1,ch2*/
ch1=?a?; ch2=?b?; /*给字符变量赋值 */
2.特性
字符数据在内存中存储的是字符的 ASCII码 ── 一个无
符号整数,其形式与整数的存储形式一样(如图 2-4所示),
所以C语言允许字符型数据与整型数据之间通用。
( 1)一个字符型数据,既可以字符形式输出,也可以
整数形式输出。
[案例 2.2] 字符变量的字符形式输出和整数形式输出 。
/*案例代码文件名,AL2_2.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码值进行算术运算。
[案例 2.3] 字符数据的算术运算。
/*案例代码文件名,AL2_3.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 [程序演示 ]
思考题,用字符形式输出一个大于 256的数值, 会得
到什么结果?
2.6.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]
2.7 算术运算与算术表达式
在C语言中,除控制语句和输入输出函数外,其它所
有基本操作都作为运算符处理。
1.五种基本算术运算符
+,-(减法 /取负),*,/,%(求余数)
( 1)关于除法运算 /
C语言规定:两个整数相除,其商为整数,小数部分
被舍弃。例如,5 / 2 = 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语言中, 整型, 实型和字符型数据间可以
混合运算 ( 因为字符数据与整型数据可以通用 ) 。
如果一个运算符两侧的操作数的数据类型不同, 则系
统按, 先转换, 后运算, 的原则, 首先将数据自动转换
成同一类型, 然后在同一类型数据间进行运算 。 转换规
则如图 2-5所示 。
1) 横向向左的箭头, 表示必须的转换 。 char和 short
型必须转换成 int 型, float型必须转换成 double型 。
2) 纵向向上的箭头, 表示不同类型的转换方向 。
例如, int型与 double型数据进行混合运算, 则先将 int
型数据转换成 double型, 然后在两个同类型的数据间进行
运算, 结果为 double型 。
注意,箭头方向只表示数据类型由低向高转换, 不要
理解为 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]
2.8 赋值运算与赋值表达式
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 */
C语言规定的 10种复合赋值运算符如下:
+=,-=,*=,/=,%=; /*复合算术运算符 ( 5个 ) */
&=,^=,|=,<<=,>>=; /*复合位运算符 ( 5个 ) */
3.赋值表达式
由赋值运算符或复合赋值运算符, 将一个变量和一个
表达式连接起来的表达式, 称为赋值表达式 。
( 1) 一般格式
变量 (复合)赋值运算符 表达式
( 2) 赋值表达式的值
任何一个表达式都有一个值, 赋值表达式也不例外 。
被赋值变量的值, 就是赋值表达式的值 。
例如,, a = 5”这个赋值表达式, 变量 a的值, 5, 就
是它的值 。
[Return]
2.9 C语言特有的运算和运算符
2.9.1 自增( ++)、自减( --)运算
1.作用
自增运算使单个变量的值增1,自减运算使单个变
量的值减1。
2.用法与运算规则
自增、自减运算符都有两种用法:
( 1)前置运算 ──运算符放在变量之前:++变量、
--变量
先使变量的值增(或减)1,然后再以变化后的值
参与其它运算,即先增减、后运算。
( 2)后置运算 ──运算符放在变量之后:变量++、
变量--
变量先参与其它运算,然后再使变量的值增(或减)
1,即先运算、后增减。
[案例 2.4] 自增, 自减运算符的用法与运算规则示例 。
/*案例代码文件名,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) 在表达式中, 连续使同一变量进行自增或自减运
算时, 很容易出错, 所以最好避免这种用法 。
2.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]