C语言程序设计教程 1
第二章基本数据类型、运算符与表达式
C语言程序设计教程 2
本章要求:
C语言的数据类型
各种类型数据的定义方法
常量与变量
各种类型数据的混合运算
强制类型变换重点:
数据类型;
数据的定义方法;
各种类型数据的混合运算
C语言程序设计教程 3
2.1 C语言的数据类型
C语言支持的数据类型非常丰富,它包括:基本数据类型,构造数据类型,指针类型,空类型四大类数据类型 构造类型指针类型 *
空类型 ( 无 值 类 型 )
void
枚举类型 enum
数组类型 [ ]
结构体类型 struct
共用体类型 union
基本类型整型 int
字符型 char
实型 ( 浮点型 )
单精度实型 float
双精度实型 double
C语言程序设计教程 4
2.2 常量、变量和标识符对于基本数据类型量,根据其取值是否可改变可分为常量和变量两种。
1.常量常量,其值不发生改变的量称为常量。常量可与数据类型结合起来分类。例如,整型常量、实型常量、字符型常量、字符串常量和符号常量。在编程过程中,常量是可以不经说明而直接引用的,而变量则必须要先定义后使用。
常用常量如下所示:整型常量,25,0,-7;实型常量:
5.6,-6.9;字符常量,‘ a’,‘ b’。
C语言程序设计教程 5
2.标识符
标识符是用来标识变量名、符号常量名、函数名、数组名、类型名、文件名的有效字符序列。
用一个标识符来表示一个常量,称之为符号常量。
符号常量在使用之前必须先定义,其一般形式为:
#define 标识符 常量
其中 #define也是一条预处理命令(预处理命令都以
"#"开头),称为宏定义命令其功能是把该标识符定义为其后的常量值。一经定义,以后在程序中所有出现该标识符的地方均代之以该常量值。一般习惯上符号常量的标识符用大写字母,变量标识符用小写字母,
以示区别。
C语言程序设计教程 6
例 2.1符号常量的使用。
#define LENGTH 30
#include <stdio.h>
void main()
{
int area,width;
width=10;
area=width*LENGTH;
printf(“area=%d”,area);}
程序运行结果:
area=300
程序分析:
使用符号常量参与运算,符号常量与变量不同,它的值在其作用域内不能改变,也不能再被赋值。使用符号常量的好处是:含意清楚;能做到“一改全改”。
C语言程序设计教程 7
3.变量
变量,其值可以改变的量称为变量。一个变量应该有一个名字,在内存中占据一定的存储单元。变量在使用之前必须进行定义 ——即为每个变量取一个名称
(变量名),同时规定它的数据类型,以便编译时根据数据类型分配存储空间。
C语言规定标识符只能由字母、数字和下划线 3种字符组成,且第一个字符必须是字母或者下划线。下面标识符的写法是合法的,可以作为变量名使用。
Sum,Class_2,data,wang_ming,_high,a8,AREA,year_m
onth_day
下面是不合法的标识符和变量名:
*data1,99sum,%yuan,$BGss,MR.tom,a1>b1,s/t
注意,编译系统区分大小写,将它们认为是两个不同的字符。所以,max和 MAX是两个不同的变量。
C语言程序设计教程 8
注意
建议变量名的长度最好不要超过 8个字符。
在选择变量名和其它标识符时应,见名知意”。
要求对所有用到的变量作强制定义,也就是“先定义,
后使用” 。
变量定义一般放在函数体的开头部分。要区分变量名和变量值是两个不同的概念。
data 变量名
56 变量值存储单元变量名
C语言程序设计教程 9
变量名实际上就是以一个名字对应,代表一个地址。
在对程序编译连接时由编译系统给每个变量名分配对应的内存地址。变量在定义时必须指定其数据类型,
以便在编译时为其分配存储单元。
|
&a?2500H |——————
2501H |---- 1250 ----- a=1250
&b?2502H |——————
2503H |---- -----
2504H |---- 123.67 ----- b=123.672505H |---- ------
2506H |——————
变量名、变量值、变量地址间的关系例如:
int a=1250;
float b=123.67;
C语言程序设计教程 10
4.变量赋初值
C语言中可有多种方法为变量提供初值。可以在变量定义的同时给变量赋以初值的方法。这种方法称为初始化。在变量定义中赋初值的一般形式为:
类型说明符 变量 1= 值 1,变量 2= 值 2,…… ;
例如:
int a=68; /*指定 a为整型变量,初值为 68*/
也可以使被定义的变量的一部分赋初值。
例如
float b,c,d=7.9;
上式指定 b,c,d为单精度实型变量,只对 d初始化,
其值为 7.9。
如果对几个变量赋予相同的初值,应写为:
int e=50,f=50,g=50;
C语言程序设计教程 11
例 2.2部分初始化数据
程序运行结果:
a=6,b=14,c=8
程序分析:
对定义的整型变量进行部分初始化,然后参与运算,并输出结果。
#include <stdio.h>
void main()
{
int a=6,b,c=8;
b=a+c;
printf("a=%d,b=%d,c=%d\n",a,b,c);
}
C语言程序设计教程 12
5.变量的地址
在定义了一个变量后,在内存中会分配相应的存储单元,将变量的值存储到该单元中。如前所述注意区分变量名和变量值这两个不同的概念。
例如,int x;
float y;
x=3;
y=3.14159;
2000
2001
2002
2003
2004
2005
x
y
2006
3
3.14159

C语言程序设计教程 13
2.3简单数据类型与表示范围
2.3.1 整型数据
1.整型常量的表示方法
整型常量就是整常数。在C语言中,经常使用的整常数有三种进制,它们分别是八进制、十六进制和十进制。
八进制前缀为,0”,十六进制前缀为,0x”,十进制无前缀。
(1)十进制整数。
如,123,-456.4。
(2)八进制整数。以 0头的数是八进制数。
如,0123表示八进制数 123,等于十进制数 83,-
011表示八进制数 -11,即十进制数 -9。
C语言程序设计教程 14
(3)十六进制整数。以 0x开头的数是 16进制数。
如,0x123,代表 16进制数 123,等于十进制数 291。
-0x12等于十进制数- 18。
(4)整型常数的后缀:
基本整型的长度为 16位,十进制无符号整常数的范围为 0~ 65535,有符号数为 -32768~ +32767。
八进制无符号数的表示范围为 0~ 0177777。
十六进制无符号数的表示范围为 0X0~ 0XFFFF或 0x0~
0xffff。
如果使用的数超过了上述范围,就必须加上后缀,L”
或,l”变为长整型数来表示。
例如,567L (十进制为 567)
注意,长整数 567L和基本整常数 567在数值上并无区别,
但是所占存储空间大小不同。对 567L而言,因为是长整型量,编译系统将为它分配 4个字节存储空间。而对 567,因是基本整型,则只分配 2个字节的存储空间。
C语言程序设计教程 15
2.整型变量
( 1) 整型数据在内存中的存放形式
数据在计算机内存中是以二进制形式存放的,例如,定义了一个整型变量 a:
int a; /*定义 a为整型变量 */
a=11; /*给 a附以初值 11*/
由于在内存中数值是以补码表示的,正整数的补码和它的原码在二进制形式上是相同的。所以,
a= 11,在内存中的存放形式如下所示。
内存中图
a 11
0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1
C语言程序设计教程 16
负数的补码:将该数的绝对值的二进制形式按位取反后再加 1。
例如:求 -11的补码:
符号位
( 2)整型的分类基本型:类型说明符为 int,在内存中占 2个字节。
短整量:类型说明符为 short int或 short。所占字节和取值范围均与基本型相同。
长整型:类型说明符为 long int或 long,在内存中占 4个字节。
C语言程序设计教程 17
有符号型:类型说明符为 signed;无符号型:类型说明符为 unsigned。
有符号型与无符号型又可与前三种类型匹配而构成:
类型名称 类型说明符 数值范围 字节数有符号基本型 [signed] int -32768~ 32767 2
无符号基本型 unsigned [int] 0~ 65535 2
有符号短整型 [signed] short [int] -32768~ 32767 2
无符号短整型 unsigned short [int] 0~ 65535 2
有符号长整型 [signed] long [int] -2147483648~2147483647 4
无符号长整型 unsigned long [int] 0~ 4294967295 4
上面带 [ ]的部分表示其内容可以省略
C语言程序设计教程 18
( 3)整型变量的定义变量定义的格式为:
类型说明符 变量名标识符,变量名标识符,...;
说明:允许在一个类型说明符后,定义多个相同类型的变量,并使用逗号分割变量名中多个变量,使用分号结束。类型说明符与变量名之间至少用一个空格间隔。
变量定义必须放在变量使用之前。一般放在函数体的开头部分。
在程序的同一部分,禁止对同一变量进行重复定义,在书写不同种类型变量定义时,避免都写在一行上。
对所用到的变量必须进行强制定义,即,先定义,后使用,。
int a,b,c; /*a,b,c为整型变量 */
long x,y; /*x,y为长整型变量 */
C语言程序设计教程 19
例 2.3整型变量的定义与使用
#include<stdio.h>
void main()
{long a,b;
int x,sum,ave; /*定义整型变量 x,sum,ave*/
unsigned y; /*定义无符号整型变量 y*/
a=9;
x=-10;
y=20;
b=x+a;
sum=x+y;
ave=(x+y)/2; /*不同类型数据间可进行运算 */
printf("b=x+a=%ld,sum=%d,average= %d\n",b,sum,ave);
}
程序运行结果:
b=x+a=-1,sum=12,average=6
C语言程序设计教程 20
(4)整型数据的溢出
每个整型数据都有其自身的数据类型,有其自身所占存储空间大小,基本整型 int定义的变量的最大允许存储值为 32767
例 3.4整型数据的溢出
#include<stdio.h>
void main()
{ int x,y;
x=32767;
y=x+1;
printf("%d,%d\n",x,y); }
程序运行结果:
32767,-32768
程序分析:
计算结果 -32768与实际应该的结果 32768相差一个符号,为什么呢?
数据在内存中都是以该数的补码的二进制形式存放的,32767的补码为
0111 1111 1111 1111,加 1后发生进位,变成 1000 0000 0000 0000,
最高位的 1占据了符号位,而它正好是 -32768的补码形式,所以才有上述输出结果。
C语言程序设计教程 21
2.3.2实型数据
1.实型数据表示方法实型也称为浮点型。C语言中,实数有二种形式:十进制小数形式和指数形式。
十进制数形式:由数字 0~ 9和小数点组成。注意,必须有小数点,且小数点的前面或后面必须有数字。
例如,3.1415926,0.0,0.1,7.0,780.,-25.860等均为合法的实数。
指数形式:由十进制数(基数)、加阶码标志,e”或,E”
以及指数(阶码,只能为整数,可以带符号)组成。
其一般形式为:
a E n( a为十进制数 —基数,n为十进制整数 —阶码)
其值为 a*10n。
如,1.6E2 (等于 1.6*102)
注意,阶码标志 e(或 E)之前必须有数字,且 e后的指数必须为整数。
C语言程序设计教程 22
2.实型数据在内存中的存放形式
实型数据一般占 4个字节( 32位)内存空间。与整型数据的存储方式不同,系统把一个实型数据分为 小数部分 和 指数部分 分别存放。指数部分采用规范化的指数形式表示。例如,实数 7.15731在内存中的存放形式如下:
图中是用十进制形式来表示的,实际上计算机中是用二进制来表示小数部分,以及用 2的幂次来表示指数部分的。
1+.715731+
数符 小数部分 指符 指数
+,715731× (+ 101)= 0.715731
C语言程序设计教程 23
3.实型变量的分类
实型变量分为:单精度( float型)、双精度( double
型)和长双精度( long double型)三类。
类型说明符 比特数(字节数) 有效数字 数的范围
float 32(4) 6~7 10-37~1038
double 64(8) 15~16 10-307~10308
long
double
128(16) 18~19 10-4931~104932
实型变量定义,例如:
float x,y; /*x,y为单精度实型量 */
double a,b,c; /*a,b,c为双精度实型量 */
long double z; /* z为长双精度实型量 */
C语言程序设计教程 24
4.实型数据的舍入误差
由于实型变量的存储单元能提供的有效数字总是有限的,其中单精度的有效数字是 7为,双精度的是 16位。
在有效位数之外的数字将被舍去,因此会产生误差。
例 2.5 实型数据的舍入误差。
#include<stdio.h>
void main()
{float x,y;
x=7654321.152e3;
y=x+33;
printf("%f,%f\n",x,y);}
程序运行结果:
7654321152.000000,7654321152.000000
“% f”是输出实数的制定格式。结果中 x= y,单精度的 x较 33大的多,
其有效位数是 7位,超过此范围的数字是无意义的。 Turbo C 规定小数后最多保留六位。应避免这种被,忽视,的情况发生。
C语言程序设计教程 25
5.实型常数的类型
实型常数不分单、双精度,都按双精度 double型处理。
例如定义一个实型变量 a,进行如下运算:
a= 3.14159*7.1617
编译系统先将 3.14159和 7.1617作为双精度数进行相乘的运算,得到的结果也是双精度的,然后取其前 7位有效数字赋值给实型变量 a。这样,可以使计算的结果更加精确。
C语言程序设计教程 26
2.3.3 字符型数据和字符串常量字符型数据包括字符常量和字符变量。
1.字符常量
字符常量是用一对单引号括起来的一个字符。
例如,‘ x’,‘ d’,‘ =’,‘ ! ’ 等都是合法字符常量。
注意,'d'和 'D'是两个不同的字符常量。
注意,字符常量只能是单个字符,不能是字符串。字符可以是字符集中除了单引号本身,'”、双引号,"”、
反斜杠,\”外的任意字符。但数字被定义为字符型之后就不能参与数值运算。如 '6'和 6 是不同的。 '6’是字符常量,不能参与运算。
‘a’,‘A’,‘1’
‘abc’,,a”?
C语言程序设计教程 27
2.转义字符
转义字符以反斜线,\”开头,后跟一个或几个字符。转义字符具有特定的含义,不同于字符的原意,故称,转义,字符。
如,输出函数中用到的,\n”其意义是,回车换行,
C语言中,转义字符有三种:简单转义字符、八进制转义字符和十六进制转义字符。
\n 换行
\t 横 向跳格(水平制表 8列)
\r 回 车
\\ 反 斜杠
\’ 单引号 \” 双引号
\ddd ddd表示 1到 3位八进制数字
\xhh hh表示 1到 2位十六进制数字
C语言程序设计教程 28
例 2.6 转义字符的使用。
程序运行结果:
f___ g_ c_ de
#include<stdio.h>
void main()
{ printf(,__ ab__ c\tde\rf____ \bg\n”);
}
程序分析:
注意:转义字符的作用。首先在左端输出,__ ab__ c”,然后遇到,\t”,
它的作用是跳到下一个制表符位置;一个制表符占 8列,下一制表符位置从第 9列开始,故在第 9~ 10列上输出,de”;然后遇到,\r”,它代表,回车,(不换行),于是返回到本行的行首(最左端第 1列),输出,f__
__,;然后遇到,\b”,它代表,退一格,,接着输出,g”。
程序运行时的输出结果为:
f_ abg_ c_ de
但显示器上看到的结果与上述结果不同,为:
f___ g_ c_ de
中间的字符被后续字符取代了。
C语言程序设计教程 29
3.字符变量
字符变量用来存储字符常量,它只能存放一个字符。
字符变量的类型说明符是 char。字符变量类型定义的格式和书写规则都与整型变量相同。例如:
char a,b;
4.在内存中的存储形式
每个字符变量被分配一个字节的内存空间,字符型数据在存储时,并不是把该字符本身放到内存单元中,
而是把该字符的 ASCII码值存放在变量的内存单元之中的。
例如,A的十进制 ASCII码是 65,a的十进制 ASCII码是
97
C语言程序设计教程 30
在内存单元中存放的是 65和 97的二进制代码:
字符型数据在内存中是以 ASCII码存放的,它的存储形式与整数的存储形式类似。使得字符型数据和整型数据之间可以通用。C语言允许对整型变量赋以字符值,
也允许对字符变量赋以整型值。在输出时,允许把字符变量按整型量输出,也允许把整型量按字符量输出。
C语言程序设计教程 31
例 2.7 向字符变量与整型数据通用
程序运行结果:
a,A
65,97
#include<stdio.h>
void main()
{ char a,b;
a=65;
b=97;
printf("%c,%c\n",a,b);
printf("%d,%d\n",a,b); }a,b值的输出形式取决于 printf函数格式串中的格式符,当格式符为
"%c"时,对应输出的变量值为字符,
当格式符为 "%d"时,对应输出的变量值为整数。由此可知,字符型数据和整型数据是可以通用的,但要注意字符型数据只占一个字节,它只能存放 0-255范围的整数。
C语言程序设计教程 32
例 2.8 大小写字母的转换
程序运行结果:
A,b
65,98
#include<stdio.h>
void main()
{ char a,b;
a='a';
b='B';
a=a-32;
b=b+32;
printf("%c,%c\n%d,%d\n",a,b,a,b); }
a,b为字符变量并赋予字符值,C语言允许字符变量参与数值运算,即用字符的 ASCII码值参与运算。大小写字母的
ASCII 码值相差 32,因此可以将小写字母与大写字母进行相互转换,然后分别以字符型和整型输出。
C语言程序设计教程 33
5.字符串常量字符常量是用一对单引号括起来的一个字符,而字符串常量则是由一对双引号括起的字符序列。
例如:,chongqing”,,C program”,,&1.75”,
,a”等都是合法的字符串常量。
字符串常量和字符常量是不同的量。它们之间的主要区别如下:
外形不同,字符常量由一对单引号括起来,字符串常量由一对双引号括起来。注意,'a'和 "a"是不同的。
内容不同,字符常量只能是单个字符,字符串常量则可以含一个或多个字符。
单向赋值,可以把一个字符常量赋予一个字符变量,但不能把一个字符串常量赋予一个字符变量。
空间不同,字符常量占一个字节的内存空间,字符串常量占的内存字节数等于字符串中字节数加 1。末尾增加的一个字节用于存放字符串结束的标志字符 "\0" (ASCII码为 0)。
C语言程序设计教程 34
字符串 "chongqing" 的长度是 9个字节,在内存中所占的字节为 10,其存储方式如下图所示:
最后一个字符为 '\0',在输出时是不会输出 '\0'的。
注意在书写程序时不必加 '\0','\0'是系统自动加上的。
字符常量 'a'和字符串常量 "a"虽然都只有一个字符,
但在内存中的情况是不同的。 'a'在内存中占一个字节,
"a"在内存中占二个字节。
C语言程序设计教程 35
2.3.4 各数据类型间的混合运算整型(包括 int,short,long)、
浮点型(包括 float,double)
可以混合运算。在进行运算时,
不同类型的数据要先转换成同一类型,然后进行运算,转换的原则就是为了两个运算对象的计算结果尽可能提供多的存储空间。当运算符两端的运算对象的数据类型不一致时,在运算前先将类型等级较低的数据转换成等级较高的数据 ——保值转换。
上述的类型转换是由系统自动进行的,
double float
long
unsigned
int Char,short
高低横向向左的箭头表示必定的转换纵向的箭头表示数据类型级别的高低,实际运算时不需逐级转换,可由级别低的直接转换为级别高的。
C语言程序设计教程 36
赋值号两边量的数据类型不同时,赋值号右边量的类型将转换为左边量的类型。如果右边量的数据类型长度左边长时,
将丢失一部分数据,这样会降低精度,丢失的部分按四舍五入向前舍入。
例 3.9 数据类型转换
#include<stdio.h>
void main()
{ float PI=3.14159;
int s,r=5;
s=r*r*PI;
printf("s=%d\n",s);}
程序运行结果:
s=78
PI为实型; s,r为整型。在执行
s=r*r*PI语句时,r和 PI都转换成
double型计算,结果也为 double型。
但由于 s为整型,故赋值结果仍为整型,舍去了小数部分。
C语言程序设计教程 37
2.3.5 简单数据类型的表示范围类型说明符 字节 数值范围字符型 char 1 C字符集基本整型 int 2 -32768~ 32767
短整型 short int 2 -32768~ 32767
长整型 long int 4 -214783648~ 214783647
无符号型 unsigned 2 0~ 65535
无符号长整型 unsigned long 4 0~ 4294967295
单精度实型 float 4 3/4E-38~ 3/4E+38
双精度实型 double 8 1/7E-308~ 1/7E+308
C语言程序设计教程 38
2.3.6 数据的简单输出
将数据结果展示出来,必须使用输出语句,所谓输入输出是以计算机为主体而言的。在C语言中,所有的数据输入/输出都是由库函数完成的。
在使用C语言库函数时,要用预编译命令
#include
将有关,头文件,包括到源文件中。
使用标准输入输出库函数时要用到,stdio.h”文件,
因此源文件开头应有以下预编译命令:
#include<stdio.h>

#include "stdio.h“
stdio是 standard input &outupt的英文缩写,其意思是标准输入输出。
C语言程序设计教程 39
printf函数调用的一般形式为:
printf("格式控制字符串 ",输出表列 )
其中,格式控制字符串,用于指定输出格式。,格式控制字符串,可由格式字符串和非格式字符串两种组成。格式字符串是以 %开头的字符串,在 %后面跟有各种格式字符,
以说明输出数据的类型、形式、长度、小数位数等。如:
,%d”表示按十进制整型输出;
,%ld”表示按十进制长整型输出;
,%c”表示按字符型输出等。
,%f”表示按小数形式输出单、双精度实数
非格式字符串在输出时原样照印,在显示中起提示作用。
输出表列中给出了各个输出项,要求格式字符串和各输出项在数量和类型上应该一一对应。
C语言程序设计教程 40
例 2.10 数据输出程序运行结果:
68 80
68,80
D,P
a=68,b=80
x is 3.140000
#include<stdio.h>
void main()
{int a=68,b=80;
float x=3.14;
printf("%d %d\n",a,b);
printf("%d,%d\n",a,b);
printf("%c,%c\n",a,b);
printf("a=%d,b=%d\n",a,b);
printf("x is %f\n",x);}
输出第一句中,在两 %d 之间加了一个空格 (非格式字符 ),
所以输出的 a,b值之间有一个空格。第二句中加入的是非格式字符逗号,因此输出的 a,b
间加了一个逗号。第三句要求按字符型输出 a,b值。第四句中为了提示输出结果又增加了非格式字符串。第五句的格式串要求按实型输出,其他非格式字符按原型输出。
C语言程序设计教程 41
2.4 C语言的运算符与表达式
2.4.1 C语言运算符简介
1.运算符
C语言的运算符可分为算术运算符、赋值运算符、关系运算符、逻辑运算符、位运算符、条件运算符、逗号运算符及一些特殊的运算符。
按运算符与运算对象(操作数)的关系可将 C语言的运算符分为单目运算符、双目运算符和三目运算符。
单目运算符是指运算符只需要一个操作数,如!,
++,--等;
双目运算符是指运算符需要两个操作数,即运算符的左右两侧都需要一个操作数,如 +,-,*,/,%等;
三目运算符是指运算符需要三个操作数,如条件运算符?:。
C语言程序设计教程 42
C语言的运算符可分为以下几类:
算术运算符,用于各类数值运算。包括加 (+)、减 (-)、乘 (*)、除
(/)、求余 (或称模运算,%)、自增 (++)、自减 (--)共七种。
关系运算符,用于比较运算。包括大于 (>)、小于 (<)、等于 (= =)、
大于等于 (>=)、小于等于 (<=)和不等于 (!=)六种。
逻辑运算符,用于逻辑运算。包括与 (&&)、或 (||)、非 (!)三种。
位操作运算符,参与运算的量,按二进制位进行运算。包括位与
(&)、位或 (|)、位非 (~)、位异或 (^)、左移 (<<)、右移 (>>)
赋值运算符,用于赋值运算,分为简单赋值 (=)、复合算术赋值
(+=,-=,*=,/=,%=)和复合位运算赋值 (&=,|=,^=,>>=,<<=) 条件运算符:这是一个三目运算符,用于条件求值 (?,)。
逗号运算符,用于把若干表达式组合成一个表达式 (,)。
指针运算符,用于取内容 (*)和取地址 (&)二种运算。
求字节数运算符,用于计算数据类型所占的字节数 (sizeof)。
强制类型转换运算符,强制进行数据类型转换((类型))。
分量运算符,用于存取结构和联合中的成员( →,,),其优先级在所有运算符中是最高的。
下标运算符,用于数组下标的表示( [ ]),
其他运算符,如函数调用运算符 (() )。
C语言程序设计教程 43
2.表达式
表达式是使用运算符和圆括号将操作数连接起来构成的式子。 C语言的操作数包括常量、变量、函数值等。
例如:表达式( x-y) /(3*a+b)-6*d中包括 +,-,/,*等运算符,操作数包括 x,y,a,b,3等。
C语言的运算符不仅具有不同的优先级,而且还有一个特点,就是它的结合性。
3.简单语句
C语言中,在表达式的末尾加上一个分号,;”就构成了简单语句。在程序设计过程中要避免使用无意义的简单语句。
C语言程序设计教程 44
1.赋值运算符
赋值就是将一个数据值存储到一个变量中。注意,赋值的对象只能是变量,而这个数据值既可以是常量,
也可以是变量,还可以是有确定值的表达式。赋值运算符记为,=”,其作用是将一个数据赋给一个变量。
例如,,a= 3;”其作用是执行一次赋值操作,表示将常量 3赋给变量 a。
2.赋值表达式
由赋值运算符,=,将一个变量和表达式连接的式子称为赋值表达式。其一般形式为:
变量 =表达式
例如:
x=sin(a)+(i++);
2.4.2赋值运算符和赋值表达式
C语言程序设计教程 45
对赋值表达式求解的过程是:
①求赋值运算符右侧的,表达式,的值 ;
② 赋给赋值运算符左侧的变量。
例如,赋值表达式,a =3*5”的值为 15,执行表达式后,变量 a
的值也是 15。
注意,一个表达式应该有一个值
C语言程序设计教程 46
左值 (lvalue),赋值运算符左侧的标识符
变量可以作为左值 ;
而表达式就不能作为左值 (如 a+b);
常变量也不能作为左值,
右值 (rvalue),出现在赋值运算符右侧的表达式左值也可以出现在赋值运算符右侧,因而左值都可以作为右值。
赋值表达式中的,表达式,,又可以是一个赋值表达式,
例如,a=(b=5)
分析,括弧内的,b=5”是一个赋值表达式,它的值等于 5。执行表达式
,a=(b=5)”相当于执行,b=5”和,a= b”两个赋值表达式。 赋值运算符按照,自右而左,的结合顺序,因此,,(b= 5)”外面的括弧可以不要,
即,a=(b=5)”和,a=b=5”等价,最后 a= 5。
C语言程序设计教程 47
请分析下面的赋值表达式 ∶ (a=3*5)=4*3
分析,先执行括弧内的运算,将 15赋给 a,然后执行
4*3的运算,得 12,再把 12赋给 a。最后 a的值为 12,
整个表达式的值为 12。可以看到 ∶ (a=3*5)出现在赋值运算符的左侧,因此赋值表达式 (a=3*5)是左值注意,在对赋值表达式 (a=3*5)求解后,变量 a得到值
15,执行 (a=3*5)=4*3时,实际上是将 4*3的积 12赋给变量 a,
而不是赋给 3*5。
不能写成,
a=3*5=4*3
C语言程序设计教程 48
将赋值表达式作为表达式的一种,使赋值操作不仅可以出现在赋值语句中,而且可以 以表达式 形式出现在其他语句(如输出语句、循环语句等)中,
如,printf("%d",a=b);
分析,如果 b的值为 3,则输出 a的值 (也是表达式 a=b
的值 )为 3。在一个语句中完成了赋值和输出双重功能。
C语言程序设计教程 49
3.类型转换如果赋值运算符两边的数据类型不相同,系统将自动进行类型转换,即把赋值号右边的类型换成左边的类型。具体规定如下:
( 1)整型数与实型数之间的转换
将实型数据(单、双精度)赋予整型变量时,舍去实型数据的小数部分。例如:整型变量 i,执行,i=3.14”的结果是使得
i的值为 3,以整数形式存储在内存中。
将整型数据赋给实型(单、双精度)变量时,数值不变,但以实型数据形式存储在内存中,即增加小数部分 (小数部分的值为 0)。
C语言程序设计教程 50
( 2)实型数据之间的转换
将一个 double型数据赋给 float型变量时,截取其前 7
位有效数字,存放到 float型变量的存储单元( 32位)
中。注意,数值范围不能溢出。例如:
float a;
double b=123.456789e100;
a=b;
便会出现溢出错误。
将一个 float型数据赋给 double型变量时,其数值不变,
有效位数扩展到 16位,在内存中以 64位存储。
C语言程序设计教程 51
( 3)整型数与字符型数之间的转换
字符型数据赋给整型变量时,由于字符型只占一个字节,而整型占二个字节,故将字符的 ASCII码值放到整型量的低八位中,这时有两种情况:
如所用系统将字符型数据处理为无符号型的量或对
unsigned int型变量赋值,则将字符型数据( 8位二进制位)放到整型变量的低 8位,高 8位补为 0。例如将字符 '\376'(代表图形字符,■,,其 ASCII码值为 254)
赋给 int型变量 a,如下图所示。
11 11 11 10‘\376’
a 0 0 00 00 00 11 11 11 10
C语言程序设计教程 52
如所用系统(如 Turbo C++3.0)将字符型数据处理为带符号型的量(即 signed char),如字符最高位为 0,
则整型变量高 8位补 0;如字符最高位为 1,则高 8位全补 1,见下图所示。这称为,符号扩展,,这样做的目的是使数值保持不变,如上述字符 '/376'以整数形式输出为- 2,a的值也是- 2。
1 1 11 11 10‘\376’
a 1 1 11 11 11 11 11 11 10
C语言程序设计教程 53
将一个 int,short,long型数据赋给一个 char型变量时,
只将其低 8位原封不动地送到 char型变量(截断)。例如:
int a=291;
char b='c';
b=a;
赋值情况见下图所示,字符变量 b的值为 35,如用,%
c”格式输出 b,将得到字符,#,(其 ASCII为 35)。
0 0 1 0 0 0 1 1
i=291
0 0 0 0 0 0 0 1 0 0 1 0 0 0 1 1
b=35
C语言程序设计教程 54
( 4)整型数据之间的转换
如将带符号的整型数据( int型)赋给 long型变量时,
要进行符号扩展,将整型数的 16位送到 long型低 16位中。
如 int型数据为正值(符号位为 0),则 long型变量的高
16位补 0;如 int型变量为负值(符号位为 1),则 long
型变量的高 16位补 1,以保证数值不改变。
如将一个 long型数据赋给一个 int型变量,只将 long型数据中低 16位原封不动地送到 int型变量( 截断 )。例如:
int x;
long y=9;
x=y;
赋值情况如下图所示,
C语言程序设计教程 55
如果 y=65536(八进制数 0200000),则在赋值后 x值为
0,如下图所示。
0 0 00 00 00 00 00 00 00 00 00 00 00 00 00 10 01
0 0 00 00 00 00 00 10 01
y=9
符号位 a=9
符号位
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
b=65536
符号位
a=0
符号位
C语言程序设计教程 56
( 5)无符号整数与其他整数之间的转换
将一个 unsigned int类型数据赋给一个与其长度相同的整型变量(如 unsigned int→int,unsigned
long→long,unsigned short→short )时,将
unsigned型变量的内容原样送到非 unsigned型变量中,
即进行原样复制;但如果数据范围超过相应整型的范围,则会出现数据错误。例如:
unsigned int x=65535;
int y;
y=x;
将 x整个送到 y中,如下图所示。由于 y是 int型,第 1位是符号位,因此 y成了负数。根据补码指数可知,y的值为- 1,可以用 printf( "%d",b)来验证。
C语言程序设计教程 57
将非 unsigned 型数据赋值给长度相同的 unsigned型变量,也是原样赋值(连原有的符号也作为数值一起传递),
y
x
符号位
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
C语言程序设计教程 58
例 2.11 有符号数据送给无符号变量
程序运行结果:
65535
程序分析:
赋值情况如下图所示
#include<stdio.h>
void main()
{unsigned x;
int y=-1;
x=y;
printf("%u\n",x); }
y
x
符号位
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
不同类型的整型数据间的赋值归根结底就是一条,按存储单元中的存储形式直接传送。
C语言程序设计教程 59
4.复合赋值运算符
除了基本赋值运算符外,C语言还提供了另外十种复合运算符。它们就是在赋值符,=”之前加上其它二目运算符可构成复合赋值符。如 +=,-=,*=,/ =,%=,
<<=,>>=,&=,^=,|=。这些运算符把,运算,和
,赋值,两个操作结合在一起称之为复合赋值运算符。
采用复合赋值运算符可提高代码执行效率。
构成复合赋值表达式的一般形式为:
变量 双目运算符 =表达式
它等效于:
变量 =变量 运算符 表达式
即将左边的(变量)与右边的(表达式)进行(双目运算符)所规定的运算,然后将值返回给变量。
例如
x*=y+38 等价于 x=x*(y+38)
C语言程序设计教程 60
为便于记忆,可以这样理解:
① x += y (其中 x为变量,y为表达式 )
② x += y(将有下划线的,x+”移到,=”右侧)
|___↑
③ x = x + y (在,=”左侧补上变量名 a)
注意,如 y是包含若干项的表达式,则相当于它有括号。
对赋值表达式 a+=a- =a*a,如果 a的初值为 3,则此赋值表达式求解步骤如下:
先进行,a- =a*a”的运算,它相当于 a=a- a*a,a的值为 3- 9
=- 6。
再进行,a+=- 6”的运算,相当于 a=a+(- 6),a的值为- 6- 6
=- 12。
C语言程序设计教程 61
2.4.3 强制类型转换符
强制类型转换符就是“()”,它是单目运算符,它把表达式的类型强制类型转换成圆括号中的“数据类型名”所指定的类型。强制类型转换又称为显示转换。
其一般形式为:
(类型说明符 ) (表达式 )
其功能是把表达式的运算结果强制转换成类型说明符所表示的类型。
例如:
(int) a /*把 a转换为整型 */
(float)(x+y) /*把 x+y的结果转换为实型 */
C语言程序设计教程 62
使用强制转换时应注意以下问题:
类型说明符和表达式都必须加括号,单个变量可以不加括号。例如,不要把( int) a,写成 int( a)。上式
(float)(x+y)如写成 float x+y则只是将 x转换成实型,再与 y相加。
无论是强制转换或是自动转换,都只是为了本次运算的需要而对变量的数据长度进行的临时性转换,而不改变数据说明时对该变量定义的类型。例如,(int) a,
如 a原指定为 float型,则进行强制类型转换后,得到一个 int型的中间变量,它的值等于 a的整数部分,而 a的类型不变,仍为 float型。
C语言程序设计教程 63
例 2.12 强制类型转换
程序运行结果:
x=3,a=3.140000
程序分析:
本例表明,a虽强制转为 int型,但只在运算中起作用,
是临时的,而 a本身的类型并不改变(仍为 float型)。
因此,(int)f的值为 3(删去了小数 )而 f的值仍为 3.14。
#include<stdio.h>
void main()
{float a=3.14;
int x;
x=(int)a;
printf("(x=%d,a=%f\n",x,a);}
C语言程序设计教程 64
2.4.4算术运算符和算术表达式
(1)基本的算术运算符,
+ (加法运算符,或正值运算符。如,3+5、+3)
- (减法运算符,或负值运算符。如,5-2、-3)
* (乘法运算符。如,3 *5)
/ (除法运算符。如,5/3)
% (模运算符,或称求余运算符,%两侧均应为整型数据,如,7%4的值为3)
C语言程序设计教程 65
使用上述运算符时需要注意几点:
两整数相除,结果为整数(舍去小数部分),商向下取整。如,20/7,的结果为 2,3/4的结果为 0。但是,
如果除数或被除数中有一个为负数,则舍入的方向是不固定的。例如,- 5/3,有的机器上得到结果- 1,
有的机器上得到结果- 2。多数机器采取“向零取整”
的方法,即- 5/3=- 1,取整后向零靠拢。
如参与 +,-,*,/运算的两个数中有一个为实型,则结果为 double型,因为实型都按 dounle型进行处理。
取摸运算符%实际上就是数学运算中的求余运算符,
它要求参与运算的两个操作对象均为整型。求余运算的结果等于两数相除后的余数,结果的符号与%左边的操作数的符号相同。例如,20% 3的结果为 2,45%
- 8的结果为 5(其中“-”为负值运算符),- 45%
8的结果为- 5。
C语言程序设计教程 66
例 2.13 除法及求余运算程序运行结果:
2,-2
2.857143,-2.857143
1
程序分析:
第一条输出说明除法运算中两操作数均为整数时其结果为整数,如操作数中出现负数,其结果向零取整。第二条输出说明除法运算中两操作数中有一个为实数,其结果为 double型。第三条输出说明取模运算是得到两除数的余数,结果符号与%左边的操作数的符号相同。
#include<stdio.h>
void main()
{ printf("%d,%d\n",20/7,-20/7);
printf("%f,%f\n",20.0/7,-20.0/7);
printf("%d\n",100%-3); }
C语言程序设计教程 67
2.4.5 自增自减运算符
1.自增自减运算符
在 C语言中提供了两个特殊的运算符:自增运算符
,++”和自减运算符,――” 。自增运算符,++”,其功能是使变量的值自增 1。自减运算符,――”,其功能是使变量值自减 1。它们均为单目运算,都具有右结合性,可以出现在运算符的前面或后面。有以下几种形式:
++i i自增 1后再参与其它运算。
――i i自减 1后再参与其它运算。
i++ i参与运算后,i的值再自增 1。
i―― i参与运算后,i的值再自减 1。
注意区分,++”(或,――” )出现在运算变量的前面还是后面,这决定着变量使用前进行加(减)操作,
还是使用后进行加(减)的操作 。
C语言程序设计教程 68
如 i的初值为 3,则 j=++i是先执行 i加 1后,再把 i的值 4赋给 j,最终 i和 j的值均为 4;而 k= i++是先把 i的值 3赋给 k
后,再执行 i加 1,最终 k的值为 3,i的值为 4。
使用自增、自减运算符时,需注意以下几点:
自增运算符( ++)和自减运算符( ―― ),只能用于变量,而不能用于常量或表达式。例如,++26或( a-b)
++是不合法的。
自增、自减运算符是单目运算符,其优先级高于基本的算术运算符,与单目运算符“-”(取负)的优先级相同,其结合方向是“自右至左”。
C语言程序设计教程 69
例 2.14 自增自减运算程序运行结果:
9
8
8
9
-8
-9
#include<stdio.h>
void main()
{ int i=8;
printf("%d\n",++i);
printf("%d\n",--i);
printf("%d\n",i++);
printf("%d\n",i--);
printf("%d\n",-i++);
printf("%d\n",-i--); }
程序分析:
i的初值为 8,输出语句第 1行 i加 1
后输出故为 9;输出语句第 2行减 1
后输出故为 8;第 3行输出 i为 8之后再加 1(为 9);第 4行输出 i为 9之后再减 1(为 8) ;第 5行输出 -8之后再加 1(为 9),第 7行输出 -9之后再减 1(为 8)。
注意,- i++和- i―― 之前的
,-,为负值运算符,因此按照结合性这两个表达式相当于-
( i++)和-( i―― )。
C语言程序设计教程 70
2.表达式使用中的问题说明
ANSI C并没有具体规定表达式中的子表达式的求值顺序,
允许各编译系统自己安排。
例如:对表达式 a = f1( )+f2( )
并不是所有的编译系统都先调用 f1( ),然后调用
f2( )。在有的情况下结果可能不同。有时会出现一些令人容易搞混的问题,因此务必要小心谨慎。 调用先后顺序不同,结果可能不同。
C语言中有的运算符为一个字符,有的运算符由
两个字符组成,为避免误解,最好采取大家都能理解的写法。
例如:不要写成 a+++b的形式,而应写成
(a++)+b的形式
C语言程序设计教程 71
2.4.6 位运算符、位运算表达式
前面介绍的各种运算都是以字节作为最基本位进行的。
C语言中,提供了位运算的功能,这使得C语言也能像汇编语言一样用来编写系统程序。 C语言提供了 6种位运算符,可分为两类:位逻辑运算符和移位运算符。
位逻辑运算符有 4种,它们是:
& 按位与
| 按位或
^ 按位异或
~ 取反移位运算符有 2种,它们是:
<< 左移
>> 右移
C语言程序设计教程 72
1.字节和位
在计算机中内存是以字节为单位的连续的存储空间,
每个内存单元(字节 byte)有一个唯一的编号,即地址。
一个字节一般由 8个二进制位( bit)组成,其中最右边的一位称为,最低位,,最左边的一位称为,最高位,。每个二进制位的值是 0或 1。
2.数值的编码表示
在计算机内表示数值的时候,以最高位为符号位,最高位为 0表示数值为正,为 1表示数值为负。表示数值的编码一般由:原码、反码、补码。
( 1)原码
用最高位为符号位来表示数值的符号:最高位为 0表示正数,最高位为 1表示为负数,其余各位代表数值本身的绝对值(二进制)。
C语言程序设计教程 73
如:
+11的原码是,00001011
- 11的原码是,10001011
注意,0的原码有两种不同的表示,+0的原码是
00000000,- 0的原码是 10000000。由于 0的表示方法不唯一,不适合计算机的运算,所以计算机内部一般不使用原码来表示数据。
( 2)反码
正数的反码与原码相同,如 +11的反码也是 00001011;
而负数的反码是:原码除符号位外(仍为 1),各位取反。例如:
- 11的反码是,11110100
+0的反码是,00000000
- 0的反码是,11111111
同样,0的表示方法不唯一,所以计算机内部一般也不用反码来表示数据。
C语言程序设计教程 74
( 3)补码
正数的补码与原码相同,如 +11的补码同样是 00001011,
而负数的补码是:除最高位仍为 1外,原码的其余各位求反,然后再加 1。例如:
- 11的原码是,10001011,求反(除最高位外)后,
得 11110100,再加 1,结果是 11110101。
+0的补码是,00000000
- 0的补码是其反码 11111111加 1,得 100000000,最高位溢出,剩下 00000000。
所以,用补码形式表示数值 0时,是唯一的,都是
00000000。
目前计算机通常都是以补码形式存放数据。因为采用编码形式不仅数值表示唯一,而且能将符号位与其他位进行统一加以处理,为硬件实现提供方便。
C语言程序设计教程 75
2.4.7逗号运算符和逗号表达式
在C语言中,逗号,,,的用途主要有两种:一种是作为运算符,一种是作为分隔符。用逗号把两个表达式连接起来,称为逗号表达式(又称顺序求值运算符)。逗号运算符的优先级别最低。
1.逗号作为运算符
逗号表达式的一般形式为:
表达式 1,表达式 2
其求值过程是先求表达式 1的值,再求表达式 2的值,
并以表达式 2的值作为整个逗号表达式的值。例:
逗号表达式,12- 6,9+8”的值为 17。
C语言程序设计教程 76
逗号表达式:
i= 3*5,i*2
因为,逗号表达式中表达式 1中的赋值运算符的优先级高于逗号运算符的优先级。它的求解过程为:先求解 i
= 3*5,经计算和赋值后得到 i的值为 15,然后求解 i*2
得 30,整个表达式的值为 30。
逗号表达式的扩展形式为:
表达式 1,表达式 2,表达式 3,…… 表达式 n
逗号表达式的值为表达式 n的值。
因为逗号运算符的优先级是所有运算符中级别最低的,
因此,下面两个表达式是不同的:
① j=( i= 3*5,i*2)
② j= i= 3*5,i*2
① 式是一个赋值表达式,将一个逗号表达式的值赋给 j,
j的值为 30;而 ②式是个逗号表达式,它包括一个赋值表达式和一个算术表达式,j和 i的值都是 15,整个表达式的值为 30。
C语言程序设计教程 77
2.逗号作为分隔符
逗号除了作为运算符外,还可以作为分隔符,作为 C语言的标点符号之一,用来分隔开相应的多个数据。如在定义变量时,具有相同类型的多个变量可在同一行中定义,其间用逗号隔开:
int a,b,c;
例如:
printf("%f,%f,%f",(x,y,z),y,z);
则,( x,y,z),是一个逗号表达式,它的值等于 z的值。括号内的逗号不是参数间的分隔符,而是逗号运算符。括号中的内容是一个整体,作为 printf函数的一个参数。
C语言程序设计教程 78
例 2.15 逗号运算符程序运行结果:
y= 6,x= 6
程序分析:
逗号表达式中 y=(x=a+b),(b+c),x和 y的值相同,都是
6,而整个逗号表达式的值并没有用到。
#include<stdio.h>
void main()
{ int a=2,b=4,c=6,x,y;
y=(x=a+b),(b+c);
printf("y=%d,x=%d",y,x);}
C语言程序设计教程 79
2.4.8 指针运算符,sizeof运算符
1.指针运算符
指针运算符包括用于取内容 (*)和取地址 (&)二种运算符。,*” 和,&”运算符都是单目运算符。 &运算符用来取出其运算分量的地址。 *运算符是 &的逆运算,它把运算分量(即指针量)所指向的内存单元中的内容取出来。例如:
int a,b,*p;
p=&a;/*把变量 a内存单元的地址给 p(指针变量) */
b=*p;/*把 p所指单元的内容(即 a的值)赋给变量 b*/
有关指针的详细内容,详见后续章节。
2.sizeof运算符
sizeof也是单目运算符,用来计算某种类型的变量或某种数据类型在计算机内部表示时所占用的字节数。
例如:
sizeof( float)的值为 4,表示 float型占用 4个字节。
sizeof常用来计算数组或结构所需空间大小,以便进行动态存储空间分配。
C语言程序设计教程 80
2.5 运算符的优先级和结合性
算术表达式的解就是经过算术运算得到的表达式的值。
C语言中,规定了运算符的优先级和结合性,运算符的运算优先级共分为 15级。 1级最高,15级最低。在表达式中,优先级较高的先于优先级较低的进行运算。
例如,先乘除后加减。而在一个运算量两侧的运算符优先级相同时,则按运算符的结合性所规定的结合方向处理。
C语言中规定了各运算符的结合性(结合方向),结合性分为两种,一种是左结合性 (自左至右 ),另一种是右结合性 (自右至左 )。
C语言程序设计教程 81
优先级 运算符 运算符类型 运算对象个数 结合性
1 ( ) [ ] ->,基本 1个 单目运算符 自左至右
2 ! ~ ++ ―― & * sizeof ( 类型名 )+(正)-(负) 单目 2个 双目运算符 自右至左
3 * / % 算术 2个 双目运算符 自左至右
4 + -
5 << >> 移位 2个 双目运算符 自左至右
6 < <= >= > 关系 2个 双目运算符 自左至右
7 = = !=
8 &
位逻辑 2个 双目运算符 自左至右9 ^
10 |
11 && 逻辑 2个 双目运算符 自左至右
12 ||
13?,条件 3个 三目运算符 自右至左
14 = *= /= += -= %= <<= >>= &= ^= |= 赋值 2个 双目运算符 自右至左
15,逗号 n个 自左至右
C语言程序设计教程 82
第二章小结
1,变量须先定义后使用,定义一个变量编译器将为其分配一个确定大小的存储空间。
2,在同一个作用域中,不同的变量不能同名,变量应尽量,见名知意,,增加可读性。
3,常量是在程序运行过程中其值不可改变的量,
各种数据具有一定的取值范围,超越范围,C编译程序将对数据进行截取,使数据不正确。
4,注意在对包含多种运算符的表达式求值时,必须遵循运算符的优先级和结合性;当不同类型的量进行混合运算时,运算过程涉及类型转换问题。
C语言程序设计教程 83
作业: