第 2章 C语言的数据类型、运算符和表达式
2.1 C语言的数据类型
2.2 常量与变量
2.3 C语言的基本数据类型
2.4 C语言的运算符与表达式
2.1 C语言的数据类型所谓数据结构指的是数据的组织形式。不同的计算机语言所允许定义和使用的数据结构是不同的。 C语言中的数据结构是以数据类型的形式出现的。
数据类型基本类型构造类型指针类型空类型整型字符型实型 (浮点型 )
枚举类型数组类型结构体类型共用体类型单精度型双精度型
2.2 常量与变量
2.2.1 常量和符号常量在程序执行过程中,其值始终不变的量称为常量 。
常量在程序中以两种形式出现,① 直接使用常量的值,
② 以宏定义的形式出现 。 前面一种常量是可以不经说明而直接引用的,称为直接常量或字面常量,后面一种常量用一个标识符代表,称为符号常量 。
符号常量的格式为:
#define 标识符 常量其中 #define是一条预处理命令 ( 预处理命令都以 #开头 ),
称为宏定义命令 ( 在第九章预处理程序中将进一步介绍 ),
其功能是把该标识符定义为其后的常量值 。 一经定义,以后在程序中所有出现该标识符的地方均代之以该常量值 。 习惯上符号常量的标识符用大写字母,变量标识符用小写字母,
以示区别 。
【 例 2-1】 符号常量的定义与使用 。
#define R 2 /*将半径 定义为符号常量 r*/
#define PI 3.1415926 /*将圆周率 定义为符号常量 pi*/
main ()
{ float area;
area=PI*R*R;
printf(“area=%f”,area);
}
符号常量的说明:
( 1) 符号常量名要用大写,变量要用小写,以示区别 。 程序中,不提倡使用很多的常量 。 并且,应尽量使用,见名知义,的符号常量和变量 。
( 2) 符号常量与变量不同,它的值在其作用域内不能改变,也不能再被重新赋值 。
( 3) 使用符号常量后,使得程序在需要改变常量的值时能做到,一改全改,。 例如在例 2-1中,如果需要改变圆的半径,从而计算相应的面积,只需要改动一处即可 。
2.2.2 变量在程序执行过程中,取值可以改变的量称为变量 。
C 规定,标识符只能是由字母 (A~ Z,a~ z)、数字 (0~
9)、下划线 (_)组成的字符串,并且其第一个字符必须是字母或下划线。
C语言的标识符可以分为三类:
( 1)关键字( 32个)
( 2)预定义的标识符
( 3)用户自定义标识符
2.3 C语言的基本数据类型
2.3.1 整型数据整型数据包括整型常量和整型变量。
1 整型常量整型常量就是整常数 。 在C语言中,使用的整常数按不同的进制区分,有八进制,十六进制和十进制三种表示:
( 1)十进制整常量
( 2)八进制整常量
( 3)十六进制整常量
2 整型变量
( 1) 整型变量的分类:
1) 基本整型:类型说明符为 int,在内存中占 2个字节,
其取值为基本整常数 。
2) 短整量:类型说明符为 short int或 short。 所占字节和取值范围均与基本型相同 。
3) 长整型:类型说明符为 long int或 long,在内存中占
4个字节,其取值为长整常数 。
4) 无符号型:类型说明符为 unsigned。 无符号型又可与上述三种类型匹配而构成无符号基本整型,无符号短整型,
无符号长整型,见表 2-1。
各种无符号类型量所占的内存空间字节数与相应的有符号类型量相同 。 但由于省去了符号位,故不能表示负数 。 表
2-1列出了 Turbo C中各类整型量所分配的内存字节数及数的表示范围 。
( 2) 整型变量的说明:
变量说明的格式为:
类型说明符 变量名标识符,变量名标识符,,..;
例如:
int a,b,c; (a,b,c为整型变量 )
long [int] x,y; (x,y为长整型变量 )
unsigned p,q; (p,q为无符号整型变量 )
short [int] i; (i为短整型变量 )
在书写变量说明时,应注意以下几点:
1) 允许在一个类型说明符后,说明多个相同类型的变量 。 各变量名之间用逗号间隔 。 类型说明符与变量名之间至少用一个空格间隔 。
2) 最后一个变量名之后必须以,;,号结尾 。
3) 变量说明必须放在变量使用之前 。 一般放在函数体的开头部分 。
2.3.2 实型数据实型数据包括实型常量和实型变量 。
1 实型常量实型也称为浮点型。实型常量也称为实数或者浮点数。
在C语言中,实数只采用一种进制,即十进制。它有二种形式:十进制小数形式和指数形式。
( 1) 十进制小数形式:
由正负号,数码 0~ 9和小数点组成 。,+29.56,-
56.33,0.0,.25,5.789,0.13,5.0,300.,-267.8230
等均为合法的实数 。 ( 正号可以省略 )
( 2) 指数形式:
由十进制数,加阶码标志,e”或,E”以及阶码 ( 只能为整数,可以带符号 ) 组成 。
注意字母 e或 E之前必须有数字 (整数、实数均可 ),之后必须有整数
2 实型变量实型变量分为两类:单精度型和双精度型,
其类型说明符分别为 float( 单精度说明符 ) 和 double
( 双精度说明符 ) 。 在 Turbo C中单精度型占 4个字节 ( 32
位 ) 内存空间,其数值范围为 3.4E-38~ 3.4E+38,只能提供 7位有效数字 。 双精度型占 8 个字节 ( 64位 ) 内存空间,
其数值范围为 1.7E-308~ 1.7E+308,可提供 16位有效数字 。
例如,float x,y,z; (x,y,z为单精度实型量 )
double a,b,c; (a,b,c为双精度实型量 )
实型常数不分单,双精度,都按双精度 double型处理 。
2.3.3 字符型数据字符型数据包括字符常量和字符变量 。
1 字符常量字符常量是用单引号括起来的一个字符 。
例如 ‘ a?,?¥ ',?4',?+',都是合法字符常量 。 "a"、
[a],{a},(a)等的界符不是单引号,均不是合法字符常量 。
‘ ab'中有两个字母字符,是字符串,而不是字符 。
另外,在C语言中,?a'与 ‘ A'是两个不同的字符常量 。
因为这两个字符的 ASCII值不同 。
C语言还允许用一种特殊的字符常量,即以 ‘ \?开头,
后跟一个或几个字符的转义字符 。 由于转义字符具有特定的含义,不同于字符原有的意义,故称,转义,字符 。
2 字符变量字符变量用来存放字符常量,即单个字符 。 不能存放字符串 。
字符变量的类型说明符是 char。 字符变量类型说明的格式和书写规则都与整型变量相同 。
例如,char ch1,ch2;
ch1,ch2被说明为字符型变量 。 系统给每个字符变量分配一个字节的内存空间,因此只能存放一个字符 。 字符值是以 ASCII码的形式存放在变量的内存单元之中的 。 如果对字符变量 ch1,ch2赋予 ‘ A?和 ‘ B?值:
ch1=?A?;ch2=?B?;
【 例 2-5】 整型量与字符型量的混合使用 。
main()
{ char ch1,ch2;
ch1=65;
ch2=66;
printf("%c,%c\n%d,%d\n",ch1,ch2,ch1,ch2);
}
【 例 2-6】 大小写字母字符的转换 。
main()
{ char ch1,ch2;
ch1='A';
ch2='B';
ch1=ch1+32;
ch2=ch2+32;
printf("%c,%c\n%d,%d\n",ch1,ch2,ch1,ch2);
}
3 字符串常量字符串常量是由一对双引号括起的字符序列 。 例如:
,CHINA,,,C program:”,,a”,,$12.5”等都是合法的字符串常量 。
字符常量占一个字节的内存空间 。 字符串常量占的内存字节数等于字符串中字符数加 1,增加的一个字节中存放尾字符 ‘ \0?(ASCII码为 0),它是字符串结束的标志 。
例如,字符串,c program”在内存中存储的内容为,c
program\0,占 10个字节内存 。
需要注意的是:字符常量 ‘ a'和字符串常量 "a"虽然都只有一个字符,但在内存中存储的情况是不同的 。
‘ a'在内存中占一个字节,可表示为,a 。
"a"在内存中占二个字节,可表示为,a和 \0 。
C语言中把除了控制语句和输入输出以外的几乎所有的基本操作都作为运算符处理 。 其运算符和表达式数量之多,在高级语言中是少见的 。 正是丰富的运算符和表达式使C语言功能十分完善,这也是C语言的主要特点之一 。
C语言中,运算符的优先级共分为 15级。 1级最高,
15级最低(见附录 B)。
优先级结合性
2.4 C语言的运算符与表达式
C语言的运算符可分为以下几类:
1.算术运算符 ( + - * / %
++ --)
2.关系运算符 (> < == >=
<= !=)
3.逻辑运算符 (&& || !)
4.位操作运算符 (& | ~ ^ <<
>>)
5.赋值运算符 (= += -= *= /=
%= &= |= ^= >>= <<=)
6.条件运算符 (?,)
7.逗号运算符 (,)
8.指针运算符 (* &)
9.求字节数运算符 (sizeof)
10.特殊运算符 (() [] →,)
2.4.1 算术运算符与算术表达式
1 基本的算术运算符用于各类数值运算 。 包括加 (+),减 (-),乘 (*),除 (/)、
求余 (或称模运算,%),自增 (++),自减 (--)共七种 。
双目运算符是有两个运算量参与运算的运算符 。 如
a+b,4- 8,c/5等都是有两个量参加运算 。
除法运算符,/” 是双目运算,具有左结合性 。 当参与运算量均为整型时,结果也为整型,舍去小数,如 5/2
的值为 2,而不是 2.5;如果运算量中有一个是实型,则结果为双精度实型,如 5.0/2的值为 2.5。
求余运算符 (模运算符 ),%” 是双目运算,具有左结合性 。 要求参与运算的量必须为整型 。 求余运算的结果等于两数相除后的余数,如 5%2的值为 1。
【 例 2-8】 输入两个整数,求平均值后输出 。
#include "stdio.h"
main()
{int m,n,k;
float ave;
printf("please input two numbers:\n");
scanf("%d%d",&m,&n);
k=(m+n)/2;
ave=(m+n)/2;
printf("k=%d ave=%f\n",k,ave);
}
2自增,自减运算符自增运算符 ( ++) 的功能是使变量的值自增 1,自减 1运算符 ( -
-) 的功能是使变量值自减 1。 它们均为单目运算,都具有右结合性 。
自增,自减运算符可有以下几种形式:
( 1) ++i /* i值自增 1后再参与其它运算 */
( 2) --i /* i值自减 1后再参与其它运算 */
( 3) i++ /* i参与运算后再将值自增 1 */
( 4) i-- /* i参与运算后再将值自减 1 */
【 例 2-9】 自增,自减运算的应用 。
main()
{ int i,m,n,p,q;
i=8;
m=i++;n=++i;
p=i--;q=--i;
printf("%d %d %d %d\n",m,n,p,q);
}
3 算术表达式算术表达式是由用算术运算符和括弧将操作数 ( 即常量,变量和函数 ) 组合起来,符合 C语言语法规则的式子 。
C语言的运算符具有不同的优先级和结合性 。 在求一个表达式值时,要先按运算符的优先级别高低次序执行,
例如先乘除后加减;如果一个运算对象左右两侧的运算符优先级别相同,则按照结合方向处理,确定是自左向右进行运算还是自右向左进行运算,如 a+b-c。
一个表达式有值和类型两个属性,它们是由计算表达式得到的结果来决定其值和类型的 。
【 例 2-10】 算术表达式的应用 。
#include "stdio.h"
main()
{ int a,b;
double x,y,z;
a=15;
b=3;
x=2.5;
y=4.5;
z=x+y*a/b;
printf("x+y*a/b=%f\n",z);
z=(x+y)*a/b;
printf("(x+y)*a/b=%f\n",z);
}
2.4.2 关系运算符与关系表达式
1 关系运算符用于比较运算 。 包括大于 (>),小于 (<),大于等于
(>=),小于等于 (<=),等于 (==)和不等于 (!=)六种 。
关系运算符都是双目运算符,其结合性均为左结合。
关系运算符的优先级低于算术运算符,高于赋值运算符。
在六个关系运算符中,前面四个的优先级相同
( >,<,>=,<=),高于 ==和 !=,==和 !=的优先级相同。
num的值等于多少?
2 关系表达式关系表达式的格式:
表达式 关系运算符 表达式上面的表达式可以是算术表达式,关系表达式,逻辑表达式,赋值表达式,字符表达式中的一种 。
C语言没有逻辑值 。 所以,若关系表达式成立,
则值为真 (即 true)返回 1,否则,表达式不成立,
则为假 (即 false)返回 0。 Turbo C中 true可以是不为 0的任何值,而 false则为 0,也就是非 0即真,
0为假 。
【 例 2-11】 关系表达式的应用 。
main()
{int a;
a=14>5;
printf("a=%d\n",a);
a=14<5;
printf("a=%d\n",a);
}
2.4.3 逻辑运算符与逻辑表达式
1 逻辑运算符用于逻辑运算 。 包括与 (&&),或 (||),非 (!)三种运算符 。 与运算符 &&和或运算符 ||均为双目运算符,具有左结合性 。 非运算符 !为单目运算符,具有右结合性 。
( 1) 逻辑运算符和其它运算符优先级的关系:
1) 逻辑运算符优先级从高到低的排列是是:
非 (!)→ 与 (&&)→ 或 (||),非 (!)优先级最高 。
2) 算术,关系,逻辑,赋值运算的优先级从高到低的排列是:
非 (!)→ 算术运算 → 关系运算 → 与 (&&)→ 或 (||)→ 赋值运算,
逻辑运算举例:
a>b && x>y等价于 (a>b) && (x>y)
!b==c||d<a等价于 ((!b)==c)||(d<a)
a+b>c && x+y<b等价于 ((a+b)>c) && ((x+y)<b)
( 2) 逻辑运算的值逻辑表达式的格式:
表达式 逻辑运算符 表达式若逻辑表达式成立,为真 (即 true)则返回 1; 否则,
表达式为假 (即 false),返回 0。
例如,5>0 && 4>2,由于 5>0为真,4>2也为真,相与的结果也为真 。
例如,5>0||5>8,由于 5>0为真,相或的结果也就为真
【 例 2-12】 逻辑表达式的应用 。
main()
{int a=14,b=15,x;
char c='A';
x=(a&&b)&&(c<'B');
printf("x=%d\n",x);
}
2.4.4 条件运算符与条件表达式条件运算符是 C语言中唯一的一个三目运算符,由,?”
和,,,组成,用于条件求值 。
条件表达式的格式:
表达式 1? 表达式 2,表达式 3
条件表达式的执行过程为:先求表达式 1的值,如果为真,则求表达式 2 的值,并以表达式 2 的值作为整个条件表达式的值;否则,求表达式 3 的值,以表达式 3的值作为整个条件表达式的值 。
条件表达式通常用于赋值语句之中 。
条件运算符的运算优先级低于关系运算符和算术运算符,但高于赋值运算符 。 条件运算符的结合性是自右至左 。
【 例 2-13】 求三个数中的大数 。
main()
{ int a,b,c,max;
printf("please input three numbers:\n");
scanf("%d%d%d",&a,&b,&c);
max=a>b?a:b;
max=max>c?max:c;
printf("max=%d\n ",a>b?a:b);
}
2.4.5 赋值运算符与赋值表达式
1 赋值运算符用于赋值运算,分为简单赋值 (=),复合算术赋值 (+=,-
=,*=,/=,%=)和复合位运算赋值 (&=,|=,^=,>>=,<<=)三类共十一种 。
例如:语句 i=1;中的赋值运算符,=”的功能是将整型常量 3赋给整型变量 i,这样 i的值就是 3。
2 简单赋值运算符与赋值表达式赋值表达式的格式:
<变量 > <赋值运算符 > <表达式 >
格式中左边只能是变量,右边是表达式,常量,变量,
函数作为表达式的特例,也可以出现在右边 。 其功能是将右边表达式的值计算出来,赋予左边的变量 。 赋值运算符具有右结合性 。
算术,关系,逻辑,赋值运算符的优先级从高到低的排列是:
非 (!)→ 算术运算 → 关系运算 → 与 (&&)→ 或 (||)→ 赋值运算例如,sum=a+b;是计算表达式 a+b的和,再赋予左边的变量 sum。
例如,a=b=c=5可理解为 a=(b=(c=5))。
C语言中,凡是表达式可以出现的地方均可出现赋值表达式 。 例如,式子 a=(b=5)+(c=8)是合法的 。 它的意义是把 5赋予 b,8赋予 c,再把 b,c相加,和赋予 a,故 a应等于 13。
按照C语言规定,任何表达式在其未尾加上分号就构成为语句 。 因此 a=b=c=5是赋值表达式,而 a=b=c=5;是赋值语句 。
3 变量赋初值在程序中常常需要对一些变量赋初值,以便使用变量 。 C
语言允许在定义变量的同时为其赋初值 。
例如:
int a=5;
float x=3.2;
char ch1='a';
赋初值时可以只对说明的一部分变量赋初值;也可以将几个变量赋予同一个初值。由于在赋值符,=”右边的表达式也可以又是一个赋值表达式,因此,变量 =(变量 =表达式 ); 是成立的,从而形成嵌套的情形。其展开之后的一般形式为,变量 =变量 =…= 表达式 ;
4 类型转换赋值表达式要求左右两边的数据类型要相同 。 如果赋值运算符两边的数据类型不相同,系统将进行转换,转换的方法有两种:自动类型转换和强制类型转换 。
( 1) 自动类型转换把赋值号右边的类型自动换成左边变量的类型 。 转换时,
要尽量保持赋值前后数据的一致性,具体规定如表 2-4
所示 。
自动类型转换发生在不同数据类型的数据混合运算时,
自动类型转换遵循以下规则:
1) 若参与运算的运算量类型不同,则先转换成同一类型,
然后进行运算 。
2) 转换按数据长度增加的方向进行,以保证精度不降低 。
如 int型和 long型运算时,先把 int型量转换 long型量,
再进行运算 。
3) 所有的实型运算都以双精度进行,即使仅含 float单精度量运算的表达式,也要先转换成 double型,再进行运算 。
4) char型和 short型参与运算时,必须先转换为 int型量 。
5)在赋值运算中,赋值号两边的数据类型不同时,把赋值号右边的类型自动换成左边变量的类型。如果右边的数据类型长度比左边长时,将丢失一部分数据,这样就会降低精度,丢失部分将按四舍五入进行舍入
【 例 2-14】 自动类型转换的应用 。
main()
{ int a,b=305;
float x;
char c1='d',c2;
x=b;a=c1;c2=b;
printf("%f,%d,%c ",x,a,c2);
}
( 2) 强制类型转换这个运算符的作用是根据给定的数据,产生一个新的数据类型 。
强制类型转换的格式:
(类型说明符 ) (表达式 )
强制类型转换的功能是把表达式的运算结果强制转换成类型说明符所表示的类型。
例如,(float) x 把 x转换为实型 float
(int)(x+y) 把 x与 y的和转换为整型 。
在使用强制转换时应注意以下问题:
1)类型说明符和表达式都必须加括号 (单个变量可以不加括号 ),如把 (int)(x+y)写成 (int)x+y则只将 x转换成 int型,
然后再与 y相加了。
2) 无论是强制转换或是自动转换,都只是为了本次运算的需要而对变量的数据长度进行的临时性转换,原来变量的类型并未改变 。
【 例 2-15】 强制类型转换的应用 。
main()
{
float x=4.8;
int i;
i=(int)x;
printf("x=%f,i=%d\n",x,i);
}
5 复合赋值运算符及表达式在赋值符,=”之前加上其它二目运算符可构成复合赋值符 。
C 语 言 中 有 十 种 复 合 赋 值 运 算 符,+=,-=,*=,/
=,%=,<<=,>>=,&=,^=,|=。 前五种是算术运算符组成的复合赋值运算符,后五种是位运算符组成的复合赋值运算符 ( 在位运算符部分介绍 ) 。
例如:
a+=5; 等价于 a=a+5;
x*=y+7; 等价于 x=x*(y+7);
r%=p; 等价于 r=r%p;
复合赋值表达式的格式为:
变量 双目运算符 =表达式等价于 变量 =变量 运算符 表达式 ( 表达式两边相当于有括弧 )
2.4.6 逗号运算符与逗号表达式
C语言中逗号,,,也是一种运算符,称为逗号运算符 。
其功能是把两个或多个表达式连接起来组成一个表达式,称为逗号表达式 。
逗号表达式的格式:
表达式 1,表达式 2,… 表达式 n
其求值过程是,先求出表达式 1的值,再求出表达式 2的值 ……,依次求出各个表达式的值,并以表达式 n的值作为整个逗号表达式的值 。
逗号运算符是所有运算符中级别最低的 。
程序中使用逗号表达式,通常是要分别求逗号表达式内各表达式的值,并不一定要求整个逗号表达式的值 。
逗号表达式常用于 for循环中 。
并不是任何逗号都能作为逗号运算符,组成逗号表达式 。
例如在变量说明中,函数参数表中出现的逗号只是用作各变量之间的间隔符 。
2.4.7 位运算符
C语言既具有高级语言的特点,又具有低级语言的特点,
因而使用范围很广 。
C语言的位运算的功能,使得它能够编写系统程序,这是与其他高级语言不同之处 。
所谓位运算,就是参与运算的量按二进制位进行运算 。
C语言的位运算符包括 &(按位与 ),|(按位或 ),^(按位异或 ),~ (取反 ),<<(左移 ),>>(右移 ) 六种 。
除了,~,为单目运算符以外,其余五种均为双目运算符 。
位运算的运算对象只能是整型或字符型数据,不能是实型数据 。
1,按位与,运算符 (&)
按位与运算符的功能是对参与运算的两个数据,按二进位进行与运算 。 只有对应的两个二进位均为 1时,结果位才为 1,否则为 0。
即 0&0=0 0&1=0 1&0=0 1&1=1
根据按位与运算的规则可知:与 1相与值不变,与 0相与值为 0。 这样,需要保留的位与 1相与,需要清 0的位与
0相与,使得按位与运算有一些特殊的用途 。
2,按位或,运算符 (|)
按位或运算符的功能是对参与运算的两个数据,按二进位进行或运算 。 两个对应的二个二进位中只要有一个为 1时,结果位就为 1。
即 0|0=0 0|1=1 1|0=1 1|1=1
根据按位或运算符的规则可知:与 1相或值为 1,与 0相或值不变 。 这样,需要保留的位与 0相或,需要置位的位与 1相或,使得按位或运算有一些特殊的用途 。
按位异或运算符的功能是对参与运算的两个数据,按二进位进行异或运算 。 当两对应的二进位相异时,结果为 1;相同时,结果位 0。
即 0^0=0 0^1=1 1^0=1 1^1=0
根据按位异或运算符的规则可知:与 1相异或值变反,与
0相异或值不变。这样,需要保留的位与 0相异或,需要变反的位与 1相异或,使得按位异或运算有一些特殊的用途 。
4,求反,运算符 (~ )
单目运算符,具有右结合性 。 其的功能是对参与运算的数据,各二进位求反,1变为 0,0变为 1。
5,左移,运算符 (<<)
按位左移运算符的功能是把左移运算符,<<,左边的运算对象的各二进位全部左移若干位,移动位数由,<<”
右边的数指定 。 移动时,高位左移后溢出丢弃,右边低位补 0。
例如,a<<3 指把 a的各二进位向左移动 3位。如
a=00000111(十进制 7),左移 2位后,变为 00111000(十进制 56),相当于乘以 23。
6,右移,运算符 (>>)
按位右移运算符的功能是把,>>,左边的运算对象的各二进位全部右移若干位,移动位数由,>>”右边的数指定 。 移动时,低位右移后溢出丢弃 。 左边高位,对于无符号数,补 0;对于带符号数,最高位原来为 0,则补 0;最高位原来为 1,则补 1。 最高位是补 0或是补 1
取决于编译系统的规定 。
例如:设 a=16,a>>3 表示把 00010000右移为
00000010(十进制 2),相当于除以 2
7,复合赋值,运算符
C 语 言 中 十 种 复 合 赋 值 运 算 符 (+=,-=,*=,/
=,%=,<<=,>>=,&=,^=,|=)中的后五种是位运算符组成的复合赋值运算符 。
复合赋值表达式的格式:
变量 双目运算符 =表达式等价于 变量 =变量 运算符 表达式 ( 表达式两边相当于有括弧 )
例如,a&=b相当于 a=a&b,而 a|=b则相当于 a=a|b。