1、语言第二章 C 语言的数据类型和运算1第二章 C 语言的数据类型和运算2.1 数据类型数据是计算机加工处理的对象,C 语言中的数据包括:常量、变量和有返回值的函数。为存储和处理的需要,将数据划分为不同的类型,编译程序为不同的类型分配不同大小的存储空间(存储单元的字节数) ,并对各种类型规定了该类型能进行的运算(运算符集) ,任何类型数据的值均被限制在一定的范围内,称为数据类型的值域(取值范围) 。2.1.1 C 的数据类型说明: 构造类型是由基本类型按一定的规律构造而成的。 空类型的作用:表示函数没有返回值;说明函数无参数;表示指针不指向任何值。2.1.2 数值型数据的表示与存储形式如 的表示
2、: 日常表示 语言中的表示小数点的位置是浮动的,称为浮点数形式。在计算机内部实数都以浮点形式存储,如float 占 4 个字节,三个字节存数字部分,一个字节存指数部分。短整数 short (16bit)整数 int (16bit)长整数 long (32bit)基本类型(简单类型)数值类型整型实型(浮点型)单精度型 float (32bit)双精度型 double (64bit)字符类型 char (8bit)枚举类型 enum构造类型(组合类型)(导出类型)数组类型结构类型 struct联合(共用) 类型 union文件类型 FILE指针类型空类型 voidC的数据类型3.14159*100
3、 3.14159e00.314159*101 0.314159e+10.0314159*102 0.0314159e231.4159*10-1 31.4159e-13141.59*10-3 3141.59e-3尾数部份 指数部分语言第二章 C 语言的数据类型和运算2小数点的位置是固定的,称为定点数,如:3.14159 ,10,-20, 1992 显然整数都属于定点数,如:整数 10,在计算机内部一般占 2 个字节。定点数的小数点一般是在最高位(定点小数) 或在最低位(定点整数) 。对于实数型定点数如:3.14159,语言则把它按指数形式存放 3.14159e0,即的实数一律以浮点形式存储。2.
4、1.3 字符型数据的表示和存储形式字符型数如:(a,A,#,3)在内存中以相应的 ASCII 代码存放(占一个字节) ,如a 的 ASCII 代码为 97,存储形式为:在中,ASCII 代码值可以被看成整数,如A+32 为 97 与a 等价。2.1.4 基本类型的名字和长度下列关键字称为类型区分符:char、 int、 short、 long、 signed 、unsigned 、float、double类型区分符代表一个基本类型的名字,用来说明一个数据的类型。表 2.1 基本类型的名字和长度完整的类型名 简单的类型名类型的长度(字节)取值范围char char 1 有符号:-128127 无
5、符号:0255signed char signed char 1 -128127Unsigned char Unsigned char1 0255int int 2 或 4(与具体机器有关)字节:-32768327674 字节:约-21 亿21 亿short int short 2 -3276832767long int long 4 约-21 亿21 亿signed int signed 2 或 4 (同int)同 intUnsigned int unsigned 2 或 4(同 int) 字节:0655350 . 3 1 4 1 5 9 + 1数字部分(3 个字节) 指数部分(1 个字节)
6、0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 00 1 1 0 0 0 0 1语言第二章 C 语言的数据类型和运算34 字节:约 042 亿signed short int signed short 2 -3276832767Unsigned short intunsigned short2 065535singed long int signed long 4 约-21 亿21 亿Unsigned long intunsinged long4 约 042 亿float float 4 绝对值约13.4e-3813.4e+38double double 8 绝对值约:1.7e-3
7、081.7e+308long double long double =8 由具体实现定义说明:signed 和 unsigned 不能同时修饰 char,short 和 long 或 signed 和 unsigned 不能同时修饰 int。float 不能使用任何修饰词,double 可用 long 修饰;int 的长度与具体机器的字长相同,在 16 位机上为 2 字节,在 32 位机上为字节。因此,int 的长度与 short 或 long 相同。signed char 用个字节的低位表示字符值,最高位表示符号。unsigned char 用整个字节表示字符值,无符号位。 char 表示有
8、符号和无符号与具体机器系统有关,但 char 一定和 signed char 或 unsigned char 其中之一同。在多数机器系统中,char 与 signed char 同。浮点类型的范围与浮点在机器内的表示有关,标准没有规定浮点数格式,大多数机器浮点数格式为:对于个字节浮点数,阶码占位,尾数占位,位符号位:对于个字节的浮点数:在浮点数中尾数位决定精度(有效数字位数) ,阶码决定取值范围。对于带符号的数据类型,一般用最高位(左边第位)表示符号,表示正,表尾 数 阶码符号位(1 位) 23 位 8 位尾 数 阶码符号位(1 位) 52 位 11 位语言第二章 C 语言的数据类型和运算4示
9、负,数值以补码形式存放(一个正数的补码是该数的二进制数) ,如() 补 为0000000000001010。一个负数的补码为取反加,如() 补 为 1111111111110110。表中列出的 short,int, long 是带符号的(隐含 signed);对于无符号的数据类型,最高位不作为符号,与其它各位一起表示数值,因此,无符号数只表示正数不表示负数,与同样长度的带符号正数相比表示的最大数扩大了一倍。字符型数据也分为 signed 和 unsigned。ANSI 标准 ASCII 码字符的允许取值范围为0127,用位表示就可以了,最左位补表示正数。有些计算机系统,除 ASCII 码字符外
10、,还扩展使用一些图形符号(如“” ) ,扩充使用用 128255,其第一位为。因此,对signed 字符型数取值范围为-128127。对 unsigned 字符型,取值范围为 0255; 实数类型数据 signed、unsigned 之分;以后各章均使用类型的简写形式;语言提供了一个测试某一类型数据所占存储空间长度的运算符 sizeof,格式为sizeof(类型标识符)。如 sizeof(char)为, sizeof(long)为。2.2 常量和变量的常量有两种形式:一种是文字常量,简称常量或常数,文字常量是由表示值的文字本身直接表示的常量,如 123,3.14159;另一种是符号常量,是用标
11、识符表示的文字常量(标识符一般用大写英文字母) ,标识符是文字常量的名字。任何一个常量都属于一个数据类型,文字常量的类型由文字常量自身隐含说明,如 123 为整型,3.14159 是一个浮点型,符号常量的类型由定义时指定。2.2.1 常量的表示的常量有整数常量、浮点常量、字符常量、字符串常量和枚举常量。整数整数有三种形式:十进制整数、八进制整数和十六进制整数。十进制整数十进制整数由数字 09 组成的数字串,多位数时最左第一个数字不能为,前面可以有表示正负的符号“”或“” , “”可以省略。如 738 -50 0 +39 是合法的整数。八进制整数八进制整数由数字 07 组成的数字串,第一个数字必
12、须为 0(前导零) ,它是八进制数的标志,八进制一般用于表示无符号数如:0137 027 +013 -024 是合法的八进制整数,而 0128 非法。八进制可以与十进制转换:如 0137= 95若将转换为八进制:01888 11 余余余 即:语言第二章 C 语言的数据类型和运算5十六进制整数十六进制整数是由数字 09 和字母 af(或)组成的符号串,符号串必须以x 或X(十六进制的前缀)开头,十六进制表示无符号整数,如 0x13a 0xc32 0xff 0xb800 0xdc 都是合法的十六进制整数。013a x13a 13a 均为非法。说明:所有整数的缺省类型是 int,通过在其后面加后缀字
13、母,可以表示长整数(long)无符号整数(unsigned)和无符号长整数(unsigned long)。长整数:在任意进制整数后面加 l 或,如 27l 018l 0x1aL 无符号整数:在任意进制整数后加 u 或。如 27u 0400U 0x1aU 无符号长整数:任意进制的整数后加 ul 或 UL。如:27ul 0400UL 0x1aUL.后缀字母大小写任意,由于 l 与数字容易混,常用。当整数的值超出 int 类型所能表示的范围时,称为整数溢出。整数溢出会产生不正确的结果,为避免溢出或类型转换的需要,应根据具体情况将整数相应地表示为长整数、无符号整数或无符号长整数,如在 16 位机上,整
14、数 123456 会产生溢出,应表示成123456L.2、浮点数浮点数的一般形式为:整数部分 .小数部分 en其中 表示可选项,en 称为指数部分,en 表 n, “e”可以写成“” 。n 称为阶码(位十进制无符号常整数,可以有前导但仍表示十进制) ,n 前面的“”可以省略。如-123.567e+5 -123.567E5 -123.567e05 都是代表值-12356700.0浮点数的组成规则如下: 一个浮点数可以无整数部分或小数部分,但不能二者均无。 一个浮点数可以无小数点或指数部分,但不能二者均无。例如:3.141593 .1E+02 -.234e+5 243.e-2 2.01234e+3
15、 0. .08 100.0 都是合法的浮点数。若将 2.01e+3 写成 2010,将. 写成,或将 100. 写成 100 则它们不是浮点数而是整数。下面一些是非法表示:-.e+1 既无小数部分也无整数部分0.1e-0.5:阶码不是整数0.1e+I:阶码不是常量(除非 I 已定义为符号整型常量)当浮点数超出它的类型所能表示的范围产生浮点溢出。如果浮点数的绝对值小于所能表示的最小值则下溢。如 1.7e-309 和-1.7e-309 均产生下溢。下溢时绝对值太小以致机器不能表示而产生零值,称之为“机器零” 。下溢时机器可能不能正常运行。当浮点数的绝对值语言第二章 C 语言的数据类型和运算6大于所
16、能表示的最大值时产生上溢,如 1.7e309 和-1.7e309 均产生上溢。上溢时将产生错误的结果。浮点数的缺省类型是 double,通过在浮点数后面加后缀字母可以表示单精度(float)数、双精度数(double)和高精度 (lang double) 数。单精度浮点数:在浮点数后面加 f 或 F。如:3.14159F。双精度浮点数:在浮点数后面加 d 或 D。如:3.14159d。高精度浮点数:在浮点数后面加 l 或 L。如:3.14159L。在程序中可根据存储的需要、精度的需要或类型转换的需要将浮点数表示为适当的类型。3、字符常数字符常数通常是指一对单引号(单撇号)括起来的 一个 字符,
17、形式为:字符字符常数可以被看成是一个整数,值为该字符的 ASCII 码值。字符常数有两种表示方法。(1) 用字符的图形符号表示一个字符,形式为:字符的图形符号字符的图形符号是指可打印字符,ASCII 码字符集中,字符码为 32126 的字符是可打印字符,因而这种方法只适用于部分字符。如: a B + 3 注意:a 和 a 表示两种完全不同的概念,a是一个字符常数,a 是由单个字母构成的标识符。另外,在可打印字符中,有两个特殊字符不能用图形符号来表示,它们是单引号本身( )和反斜线() 。即 是非法表示,要想表示它们必须用转义序列表示。(2)用转义序列表示一个字符,形式为:转义序列转义序列是由反
18、斜线()开头的一个特殊字符串,每个转义序列表示字符集中的一个字符,转义序列及其表示的字符如表 2.2 所示。表 2.2 转义序列ASCII 字符码 表示的字符转义序列 十进制 八进制 十六进制0abfnrtv07812101391107100140120150110130x000x070x080x0c0x0a0x0d0x090x0b空字符响铃字符退格字符换页字符换行字符回车字符水平制表字符垂直制表字符语言第二章 C 语言的数据类型和运算7?”oooxhh92633934025502551340770470420003770003770x5c0x3f0x270x220x000xff0x000xf
19、f反斜线字符问号字符单引号字符双引号字符以 ooo 为字符码的字符以 xhh 为字符码的字符说明:()从表中可以看出,转义序列有两种形式:一种是反斜线后跟一个图形符号;另一种转义序列的位型“ooo ”和“xhh” 。前者表示常用的控制字符(字符码为 031 的字符),如n表示一个换行字符,其 ASCII 码为十进制 10。后者可以表示字符集中的任一字符(字符码为 0255 的所有字符) 。()位型中的 ooo 表示个八进制数字,可以不用前缀;hh 表示个十六进制数字,x 是前缀不能省。例如:水平制表符可用下列任一种形式表示:t 011 11 x0b xb字符 A 可用下列任一种形式表示:A 1
20、01 x41 ()单引号和反斜线字符虽然是打印字符,但编译程序规定必须用转义序列表示。例如:单引号字符可用下列任一种形式表示: 047 47 x27反斜线字符可用下列任一种形式表示: 0123 123 x5c()双引号字符常数可以用图形符号或转义序列任一种形式表示。例如: “ ” 042 x22()字符0是值为的字符(空字符) ,不是空白字符。 0除表示值外,它强调对象的类型是字符型。也就是说,表示值为的字符用0比用好。、字符串C 语言没有字符串类型,但可以表示字符串常数,字符串变量是用字符数组来表示的。字符串常数(简称字符串)是用一对双引号括起来的一个字符序列,其字符的个数称为字符串长度。形
21、式为: “字符序列”双引号是字符串的定界符而不是字符串的组成部分,双引号中的任何一个字符都是一个字符常数,形式为不带单引号的字符(图形符号或转义字符) 。例如:“This is a stringn”一个字符串可以包含个字符,表示为“” (两个相邻的双撇号) ,称为空串。字符串在机内存储时,系统自动在其末尾加了一个0 , 0是字符串的结束标志,以确定字符语言第二章 C 语言的数据类型和运算8串的实际长度,字符串的存储长度比实际长度大。空串的存储长度为,存储长度为。注意:() “a” 和a是两个不同的概念。()当双引号作为字符串的组成字符时,必须用转义序列表示。如:“” is a empty st
22、rinng”表示:“” is a empty strinng()当单引号作为字符串的组成字符时,可以用图形符号表示,也可以用转义字符表示,如:“Its a pen.” “Its a pen.”()字符串可以连接。被连接的两个字符串之间可以有个或多个空白字符,但不能有其它字符。如:“Hello,” “how are you?” 等价于“Hello, how are you?”字符串连接主要用于源程序中表示长度跨越多行的字符串。如:printf(“Hello,how are you?”); 是非法的。因为语法规定字符串常数必须书写一行。如果一行写不下可用两种方法:printf(“Hello,How
23、 are you?”); 是续行符 或: printf(“Hello,”“how are you:”);语言第二章 C 语言的数据类型和运算92.2.2 符号常量为使程序易于阅读和便于修改,可以给程序中经常使用的常量定义一个有一定含义的名字,这个名字称为符号常量。符号常量是一个标识符,有三种方法定义一个符号常量:一种是利用编译预处理的宏替换功能#define;另一种是用 const 类型限定符说明并初始化一个标识符;第三种方法是通过定义枚举类型来定义符号常量(以后讲) 。1. 用#define 定义符号常量形式:#define 标识符 常量表达式常量表达式是值为常量的表达式,一般为已定义的符号
24、常量或文字常量,也可以由运算符连接常量形成的表达式;标识符是符号常量的名字,它代表常量表达式所表示的文字。例如:#define SIZE 100#define PI 3.1415926#define BLANK #define TWO_PI 2.0*PI注:符号常量的名字(标识符)一般用大写字母。#define 行不是 C 语句,而是编译程序的预处理控制,因此其后面不加“;”2. 用 const 定义符号常量。形式:const 类型区分符 标识符=常量表达式;符号“=”左边的标识符被定义为常量,标识符代表常量表达式的值。例如:const int MAX=1000;const double PI
25、=3.14159;const char BLANK= ;const signed TRUE=1,FALSE=0;说明:用#define 和 const 定义的符号常量在实现上有本质不同。#define 在编译预处理时用常量表达式去替换程序中所有出现的常量标识符,标识符没有对应的存储单元;由const 说明的标识符是一个不可更改的左值,编译时要给它分配存储单元。应用举例:计算圆柱体的体积 V=r 2h#include “stdio.h”void main (void) float v,r,h;printf (“input r,h:”);scanf (“%f%f”,printf (“v=%fn”,
26、v);如果使用符号常量:#include “stdio.h”#define PI 3.14159语言第二章 C 语言的数据类型和运算10viod main(void) float v,r,h;printf(“input r,h:”);scanf (“%f%f”,与int age; int index;等价程序中有些变量在使用前需要设置初值,如做为计数器使用(如 n+;)和做累加和的变量(如 sum=sum+x)通常置初值为零,做累乘积的变量(如 time=time*y;)通常置初值为1。给变量赋初值有两种方式:一是通过赋值语句置初值(如 i=0;) ;另一个方式是在变量说明时给出初值称为初始化
27、,格式为:类型区分符 变量名=表达式,;如:int age=15,index=1,i=0,j=0;int i=j=0; 非法。因为 i=j=0 等价于 i=(j=0),而(j=0)是赋值表达式。int i,j=0; j 被初始化为 0;i 的初值不确定。char c=y;double esp=1.0e-5;注意:引用一个没有值的变量非法。2.3 运算符和表达式C 的运算符十分丰富。由运算符通过对运算对象(操作数)进行各种操作,按操作数的数目可将运算符分为:单目(一元) ,双目(二元)和三目(三元)运算符;按运算符的功能分类有:算术运算符、关系运算符、逻辑运算符、自增和自减运算符、位运算符、赋值
28、运算符和条件运算符。另外还有数组的下标 、 函数调用( ) 、表顺序求值的逗号运算符和类型强制运算符等。表达式是由运算符、操作符数组成的符合的语法算式。从本质上说,表达式是对运算规则的描述并按规则执行运算,运算的结果是一个值,称为表达式的值,其类型称为表达式语言第二章 C 语言的数据类型和运算11的类型。单个操作数也是表达式。常量、变量、有返回值的函数调用和用()括起来的表达式称为简单表达式。由简单表达式和以简单表达式为操作数的表达式都是表达式。如 y3(x4) “”称为赋值运算符表达式的运算规则是由运算符的功能和运算符的优先级与结合性决定的。为使表达式按一定的顺序求值,编译程序将所有运算符分
29、成若干组,每组规定一个等级称为运算符的优先级,优先级高的先执行运算。处于同一优先级的运算符的运算顺序称为运算符的结合性。运算符的结合性有从左至右(左结合)和从右至左(右结合)两种。表 22 运算符的优先级和结合性优先级运算符 结合性1 () 左结合2 ! (单目) (单目) a=i+(j%4!=0); 语言第二章 C 语言的数据类型和运算13最后 a 的值为 字符比较按 ASC码进行ba为 aA为 a=x+1=a) 或 c=a其结果如果变量 c 的值是小写字母,则上式为真(非 0)否则为 0。d9 若 d 为非数字时,表达式为非 0 。否则为 0!i 等价于 i= =0 但!i 比 i= =0
30、 效率高,若 c 为字符型,检查 c 是否为空白字符时 用!c 比 c= =0好注意:对于逻辑与(i1i1|k=i+j其结果整个表达式的值为 1(真) ,k 的值为。234 自增和自减运算自增和自减运算符包括:+(增 1) -(减 1) “+”和“-”是单目运算符,操作数必须是可更改的左值表达式。左值表达式是一个表示存储单元的表达式,一般为不带 const 说明的变量名。带 const 说明的标识符是不可更改的左值表达式。可更改的左值表达式包括:基本类型的变量名、下标表达式、指针变量名和间接访问表达式(指针变量) 、结构成员选择表达式和结构变量名。用()括起来的左值表达式也是左值表达式。“+
31、+”将操作数加 1, “ -”将操作数减 1,结果类型与操作数类型相同。整型或浮点型操作数按整型数值 1 增加或减少,指针类型操作数以后讲。语言第二章 C 语言的数据类型和运算14“+ +”或 “ -”可以出现在操作数前面(前缀式)或后面(后缀式) 如 +n -n n+ n- 。前缀式先将操作数增(减),然后取操作数的新值作为表达式的结果。例如若 n=1 则 +n 结果为 2,n 的新值为 2。后缀式将操作数增(减) 1 之前的值作为表达式的结果。操作数的增(减)1 运算是在引用表达式的值之后完成的称为后缀+(或)的计算延迟。一直延迟到出现下面情况时,操作数才增(减)逻辑与运算符 x+x+ 结
32、果为。整个表达执行完后 x 值为。即若 z=x+x+ 则 z 的值为,x 的值为 2。 yx+printf(“x=%d,y=%dn”,x,y);printf(“x+=%dn”,x+);printf(“d=%dn”,y);printf(“x=%d,y=%dn”,x,y);输出:x=0,y=1;x+=0y=1x=1,y=0注:自增(自减)运算符的结合性是自右至左。它的运算对象只能是整型变量,而不能是表达式或常数,如 5+或(x+y)+非法,+x 也是非法。若 x 为 5,y 为 5,z=x-y,则 x=4,y=5,z=0。2.3.5 位运算任何数据在计算机内部都是以二进制码形式存储的。例如一个 u
33、nsigned char类型的字符A存储形式为 01000001。位运算是以逐个二进制位为直接处理对象的运算。这是 C 语言区别于其它高级语言的特色之一。语言第二章 C 语言的数据类型和运算15位运算符是指 (求反) short z=-8;(1) x3该表达式的值为,表达式的类型与 y 相同。Y=15 即 0xf 二进制是 0000000000001111 右移位后 变成 0000000000000001 为整数 1。y3等价于 y/2/2/2 或 y/(2*2*2),即:yn 相当于 y 整除 2n。()z 该表达式的值为-2,类型为 intz=-8=1111111111111000(的补码
34、) ,右移位后z=1111111111111110(的补码)=-2位操作综合应用举例:例将整数的低字节作为结果的低字节,的低字节作为结果的高字节拼成一个新的整数。(P j=5.6;则 j 的值为;表达式的结果和类型与左操作数相同。对于基本类型,赋值表达式的形式可具体化为:变量名表达式例如:int i=5,j;float a=3.0,b=3.5;double r;char c1,c2;c1=a;j=c1; /*由 char 向 int 转换,结果赋给 j*/r=a*b+I; /*a*b 的结果由 float 向 double 转换,结果赋给 r*/c2=j; /*j 由 int 向 char 转
35、换,其结果赋给 c2*/i=c1c2; /*c1c2 的类型与左操作数相同,直接赋值*/当右操作数又是一个赋值表达式时,形成多重赋值表达式,例如:i=j=0 是一个合法的赋值表达式, “”右结合。因此上式等价于 i=(j=0) ,而 j=0 表达式的值为,因此 i 的值也为,但要注意:多重赋值表达式不能出现在变量说明中,如:int i=j=0; 是非法的。2.复合赋值复合赋值运算符包括+ = - = * = / = % = 应是 b=b*(a+2); c=b;而不是 b*=a; c=b+2; 赋值操作右结合。 如 x=i+j; 应如何理解:x=(i+)+j 或 x=i+(+j)?语言第二章 C
36、 语言的数据类型和运算18C 编译器总是从左至右尽量地将若干字符组成一个运算符。上式应理解为 x=(i+)+j 诸如 i=(k=j+1)+(j=5),不同的编译器有不同的理解。在 C 中不符合交换律,在turbo C2.0 中先算 k=j+1,再算 j=5.2.3.7 条件运算条件运算符(?:)是一个三元运算符,一般形式为操作数 1?操作数 2:操作数 3操作数 1 必须为基本类型或指针类型、 (一般为整型的)表达式,操作数 2 和操作数 3可以是其它任何类型的表达式,且类型也可以不一致。条件运算符的规则如图所示:注意:e2 和 e3 中只有一个被求值。表达式结果的类型取决于 e2 和 e3:
37、如果 e2 和 e3是不同的基本类型,则进行一般算术转换,结果为转换后的类型;如果 e2 和 e3 是指针,若其中一个指向 void,则另一个被转换为指向 void 的指针;若 e2、e3 一个是指针,另一个是常量,则结果类型是指针。例 1 设 i 类型为 int,则 (i,0)? i:i结果为 i 的绝对值,类型为 int.例 2(d=0)? 1:-1 结果为 d 的符号。例设 a,b 的类型为 int,则(ab)?a:b 结果为 a,b 中较大的一个。例设 ch 为 char 类型(ch=a short e,f;给出下列表达式的结果和类型。(1) a=i=j; (2) i!=j; (3) !k; (4)b=!i; (5) i j;(6) c=i|j; (7) d=2*i; (8) k; (9) e=i; (10) f=k;写一个表达式,将整数的高字节作为结果的低字节,的高字节作为结果的高字节,拼成一个新整数。语言第二章 C 语言的数据类型和运算24写一个表达式,如果是大写字母,则将转换成对应的小写,否则的值不变。写一个表达式,其结果是三个数中最大一个。