1、数据类型是程序设计语言的重要概念,是高级语言区别于低级语言的显著特征。不同的数据类型在计算机内部的存储方式不同,允许的运算不同,适用的领域也不同。,第2章 基本数据类型、常量和变量,C语言允许使用的数据类型有以下三类:(1)基本类型 不可再分的最基本的数据类型,包括整型、浮点型,双精度型、字符型及无值类型等。基本类型通常代表单个数据。(2)构造类型 由已知的基本类型通过一定的构造方法构造出来的类型,包括数组、结构体、联合体、枚举类型等。构造类型通常代表一批数据。(3)指针类型 指针可以直接指向内存地址,访问效率高,用于构造各种形式的动态或递归数据结构,如链表、树等。,1基本数据类型及其关键字,
2、2.1 基本数据类型,表2-1 基本数据类型及对应关键字表,不同类型的数据在计算机中的存储方式是不同的,即它们的存储结构和所占的存储空间字节数并不一样,这与宿主计算机的硬件特性有关。C 语言为了提高程序的可移植性,没有对数据类型的长度和存储方式进行规定,而由不同类型的计算机上使用的不同的C编译系统自行确定。VC+ 6.0规定: char型长度为1字节,按有符号二进制补码形式存储。 int型长度为4字节,按定点有符号二进制补码形式存储。 float型长度为4字节,以浮点形式存储,阶码占8位(增码表示),尾数占24位(归一化补码表示),6位有效数字精度,分辨率约为1.110-38。 double型
3、长度为8字节,存储方式与float基本相同,阶码占11位,尾数占53位,15位有效数字精度,分辨率约为2.210-308。,2基本数据类型的存储方式和取值范围,(1)short和long可以提供不同的数据长度以满足实际使用的需要。C规定:长度 short int int long int VC+ 6.0 16bit 32bit 32 bitC规定:长度 float double long doubleVC+ 6.0 32bit 64bit 64bit (2)signed和unsigned规定了对数值符号的处理,只限于char型和int型。char signed char unsigned ch
4、arshort signed short unsigned shortint signed int unsigned intlong signed long unsigned long,3. 类型修饰符,VC+ 6.0数据类型和取值范围,2.2 常量及其类型,常量是指在程序运行过程中,其值保持不变的量。常量分为char、int、double和字符串型。其类型是由书写形式决定的。,1. 整型常数,在计算机中,整数是准确表示的。C语言可以识别十进制、 八进制和十六进制的整数。 (1)十进制整数十进制整数由正负号(或)后跟数字串组成,正号可以省略不写,且开头的数字不能为0。如1234,-23,+18
5、7,32767,5600,0 在整数后面加上后缀u或U则构成无符号整数,如123u,5678U,70000u等。 在整数后面加上后缀l或L则构成长整数,如-124783648l,1234567890L 在整数后面加上后缀ul或UL则构成无符号长整数,如3456ul,1234567890ul,(2)八进制整数以数字0打头,后跟07组成的数字串。例如:0123表示八进制常数123,相当于十进制数83。八进制整数可以加上后缀u(U),l(L)或ul(UL)分别构成八进制的无符号数、长整数或无符号长整数。例如:012345u、02765543102l、0345675026ul等。 (3)十六进制整数以
6、数字0和小写字母x(或大写字母X)打头,后跟09及AF(或af)组成的数字字母串。其中,AF(或af)分别表示十进制的1015。例如:0x2f是一个十六进制,相当于十进制的47。若在十六进制数后面加上后缀u(U)、l(L)或ul(UL),则分别构成十六进制的无符号数、长整数或无符号长整数。如:0x89ad476bu, 0x9043fecd2l, 0x98bfd5ca7ul,2. 实数,C语言中,实数是近似表示的,且只能用十进制表示。 (1)定点格式,即由正负号、整数部分、十进制小数点和小数部分组成。整数部分和小数部分都是由09组成的数字串。例如,123.45,-256.701,.543,-25
7、.,0.,.0,0.0等。(小数点必不可少) (2)指数格式,即在定点表示的基础上,后面再加上一个e或E后跟一个13位整数组成。如-1.234E18, 2.74e-02, 2.71828e0, .86e-3, 1e-2等。 书写指数格式的浮点数时,字母e或E前面必须有数字,可以没有小数点,如.2e3,2.3e,2e3是正确的,而.e3,e-3等是错误的。同时,e或E后面必须是正负整数,不能带小数点,如1.2e3.1、0.3e-0.5等是错误的。在计算机中,无论是定点表示还是浮点表示的实型常数都视为double型的。如果有必要,可以用后缀f(F)来表示float型实数,如2.6736F、12.5
8、6e-13f等。,3. 字符常量,字符常量是用单引号括住的单个字符。 (1)单引号表示法,用于可显示字符,直接用单引号(撇号)将该字符括住,即表示字符常数。如A,a,5,$,?,+等。 (2)转义字符表示法,用于不可显示字符,主要是那些控制字符如换行符、回车符、换页符等,还有一些在C语言中有特殊含义和用途的字符如单引号、双引号、反斜杠,只能用转义序列表示。例如,n、012、xa均表示换行符,因为换行符的ASCII代码八进制值12,十六进制值是a。,表2.3 常用的转义字符,【例】字符常量的表示方法#include void main() printf(“%dn“, B); / 十进制print
9、f(“%cn“, B); / 字符printf(“%cn“,66);printf(“%cn“,B+32); printf(“%d,%c,%d, %cn“, n, 0, 0, x41);,4. 字符串常量,字符串常量是用双引号括起来的0个或多个字符的序列。例如 “I am a student. “x“ / 空字符串“0107328136“I said,“good morning!“ / 含转义字符 (1)字符串常量的存储方式字符串常量存储时,按字符串中字符从左到右的顺序依次占用连续的存储单元,每个字符占1个字节,存放其对应的ASCII码。C编译系统还会自动在每个字符串常量的未尾追加一个零字符NU
10、LL(0)作为字符串的结束标识。因此,一个含有n个字符的字符串常量要占用n+1个字节的存储空间。,例如,字符串常量“I am a student“ 含有14个字符(包括3个空格字符),它将占用15个字节的存储单元。,(2)字符串常量和字符常量的区别 从表示方式上看,字符串常量是以双引号定界,而字符常量则以单引号定界,如“A“是字符串常量,A则是字符常量。 每个字符常量只占1个字节的存储单元,而字符串常量则要占用一批连续的存储单元,其所占字节数为字符串长度加1。 字符型常量通常可存放在字符型变量中,而字符串常量则必须存放在字符型数组中。 字符型常量可以与整数混合运算,而字符串常量则不可以。,2.
11、3 变量及其类型,变量是指那些在程序运行过程中其值可以改变的量。变量代表着存储器中的一个存储单元。在 C 语言中,变量具有如下三个属性: 变量分为不同的数据类型,数据类型决定了该变量存储的数据的含义。 变量分为不同的存储类型,存储类型决定了变量在计算机中的存储位置及其寿命(生命期)。 变量在程序中的定义位置决定了该变量的作用域,即起作用的范围。,1. 变量的定义,C语言规定,变量必须先定义后使用,变量的数据类型与变量名本身无关。变量定义一是定义变量的数据类型,二是定义变量的名称,三是说明变量的存储类型,其一般格式为:存储类型 数据类型 变量清单;char ch1; static int i,
12、j, k;short int si;float f1, f2;double balance, profit, loss; 变量的数据类型可以是字符型、整型、浮点型、双精度型等。,2. 变量定义的位置,变量定义的位置可以有三处:在函数体内定义的变量称为局部变量,在函数的形式参数表中定义的变量称为形参,在函数外部定义的变量称为全局变量。例如 #include int color; / 全局变量int value (int x,float y); / 形式参数 int lower,upper,step; / 局部变量char c,line; / 局部变量float data,time; / 局部变量
13、unsigned long i,j,k; / 局部变量,变量在程序中的定义位置,决定了该变量的作用域。 (1)块级作用域块是用函数体内花括号括起来的一个程序段。在块内定义的变量具有块级作用域,其作用域从变量定义处到块的结束处(即块的右花括号处)。 (2)函数级作用域函数作用域是指在函数体开头定义的变量,它们在其定义的函数内有效,即在整个函数内均可以引用。 (3)文件级作用域在函数体外定义的变量具有文件级作用域。具有文件级作用域的变量可在整个文件中访问,即从变量定义的位置开始到该源程序文件结束。 (4)程序级作用域程序级的作用域最大,在组成整个程序的所有文件中均有效。当用extern将全局变量说
14、明为外部变量后,可以使其具有程序级作用域。,【例】#include int a; / 全局变量void main() int b,c; / 函数级局部变量a=1;b=2;c=3;a=a+1;b=b+1;c=c+b; / a=2 b=3 c=6 int c; / 块级局部变量c=b*3; / c=9a=a+c; / a=11printf(“first:%d,%d,%dn“,a,b,c); / 11, 3, 9printf(“second:%d,%d,%dn“,a,b,c); / 11, 3, 6,*3. 变量的存储类型,变量的存储类型指的是变量在计算机内存中的存放位置。 (1)局部变量的存储类型
15、影响其生命期auto 型变量的生命期只限于它所在的程序段执行期间;register 型变量的生命期与auto相同,但存取速度快,个数有限;static 型变量的生命期与整个程序执行期相同。 (2)全局变量的存储类型影响其作用域static 型变量的作用域仅限于它所在的程序文件;extern 型变量的作用域可扩充到其他程序文件。在定义局部变量时,若省略存储类型说明符,则视为auto型。,4. 变量的初始化,在定义变量的同时赋予其初值称为变量的初始化。如:int a=2,b=3;double x, pi=3.1415926;char ch1=a,ch2=b,ch3=ch1;注意:如果未用stati
16、c或extern对变量进行存储类型声明,未经初始化或赋值的变量,其值是不确定的,不能引用。,关于变量初始化的说明: (1)register和auto型变量的初始化是在程序执行时完成的,若未进行初始化,其值是不确定的。 (2)全局变量和static型变量的初始化是在编译阶段完成的,这种初始化在整个程序执行期间只被执行一次。这两类变量若未执行初始化,则编译系统自动为其赋零值。 (3)全局变量和static型变量只能用常数进行初始化,而register和auto型变量则既可以用常数进行初始化,也可以用先前已初始化的变量进行初始化。,2.4 符号常量,符号常量是用标识符表示的常量。从外表看,它是标识符
17、,像变量;但实质上,它是常量,它的值不能通过赋值或输入加以改变。 1. 使用符号常量的目的 用符号常数可以清晰地看出常量所代表的物理意义,增强程序的可读性 当程序中多次出现某一个常数,就要多次书写,这样一要耗费时间,二是可能出现不一致。用符号常数就可以用较短的符号代替,从而有效地避免这两个缺点。 当程序中多次出现同一常数需要修改时,用符号常数只需修改定义,可以做到一改全改。,2. 符号常量的定义,(1)宏定义宏定义是用指定的标识符(即宏名)来代替一串字符#define 标识符 字符串 例如: #define PI 3.14159265 其中,#define是编译系统的预处理命令;PI称为宏名,
18、为了与一般变量名相区别,通常用大写英文字母表示;3.14159265作为一串字符,它没有类型和值的含义。宏定义的功能:用标识符PI来代替“3.14159265“这串字符。当宏名出现在程序中时,程序会用定义的一串字符代替宏名,然后根据上下文确定其类型和值。,定义符号常数有三种方法:宏定义、const修饰和枚举。, 宏定义必须以#define开头,行末不加分号,因为它不是C语句; 每个#define只能定义一个宏,且只占一个书写行; #define命令一般出现在函数外部,其有效范围为从开始处到本源程序文件结束; 使用宏定义时可使用已定义过的宏,称为宏定义的嵌套。例如#define PI 3.141
19、59265#define A 2*PI 编译系统只对程序中出现的宏名用定义中的字符串作简单替换,而不作语法检查。例如定义#define PI 3.14abc 后,编译系统也照样将字符串“3.14abc”替换到程序中的PI处,并 不管其含义是否正确 用宏定义还可定义更复杂的表达式或函数。,注意:,这是C语言新增加的定义符号常数的一种方法,其形式为const 数据类型 标识符常数; 例如 const int max=300; 定义了一个整型的符号常数max,其值等于300。用const修饰得到的标识符不仅有值的含义,而且有类型的含义。但在程序中却不允许再对该名称赋值,即不允许在程序中再出现诸如ma
20、x=136;max=max+136; 这样的语句。const修饰只能定义常数,不能定义函数或表达式。,(2)const修饰,【例】符号常数的定义方法。#include #define PI 3.1415926535void main() double c,a,s,v;const float RADIUS=2.5;c=2*PI*RADIUS;a=PI*RADIUS*RADIUS;s=4*a;v=4*a*RADIUS/3;printf(“Circuference=%fn“,c);printf(“Area=%fn“,a);printf(“Surface Area=%fn“,s);printf(“Vo
21、lume=%fn“,v);,printf()函数可以用于所有类型数据的格式化输出。 不同类型的数据要采用不同的格式转换说明符。,若格式控制符多于输出项,则输出不确定值;反之不输出。,2.5 不同类型数据的输入输出,2.5.1 printf()函数, 可以指定输出宽度和有效数字位数(m.n)printf(“%3d,%6d,%6.5dn”,1250,1250,1250); 输出为1250, 1250, 01250printf(“%10f,%10.2f,%.2fn“,123.456,123.456,123.456); 输出为123.456000, 123.46,123.46 可以指定浮点实数输出的宽
22、度和小数位数(%m.ne) printf(“%10e,%10.4e,%.3en“,123.456,123.456,123.456); 输出为1.23456e+02, 1.235e-02,1.23e+02, 可以指定字符串输出的宽度和子串长度(%m.ns) printf(“%3s,%10s,%10.5s,%.4sn“,“abc“,“defghij“,“klmnopqrst“,“uvwxyz“); 输出为abc, defjhij, klmno,uvwx 可以指定左对齐在缺省情况下,所有的输出右对齐,在百分号后边加一个减号,如%-m.nd、%-m.nf、%-m.ns等,可使输出左对齐,右边填充空格。
23、printf(“%-10.2f,%-5.2fn“,123.456,1.23456e2); 输出为123.46 ,123.46printf(“%-10s,%-5s,%-10.5s,%-.8sn“, “abc“, “defghij“, “klmnopqrst“,“uvwxyz“); 输出为abc ,defghij,klmno ,uvwxyz,2.5.2 scanf()函数,scanf()函数可以用于所有类型数据的输入。 scanf()函数使用说明 : 不同类型的数据要采用不同的格式转换说明符; 只使用格式转换说明符 ; 输入项必须用地址表示;,scanf()函数可以用于所有类型数据的输入,采用不同
24、的格式转换说明符将不同类型的数据从标准输入设备读入内存。其调用的一般形式为 scanf(“格式控制字符串“,输入项目清单); 其中,格式控制字符串通常只包含格式转换说明符,而不使用转义字符和普通字符。, 当需要一次输入多个数据时,各数据之间只能用空格、制表符或回车键分隔,其他符号都不能作为分隔符。 在格式控制字符串中通常只出现格式转换说明符,如果出现格式转换说明符以外的字符,这些字符应该照原样输入,否则当scanf()函数从输入数据中找不到这样的字符时,将自行终止输入。 scanf(“%d%d“,其中a和b都是int型变量,若从键盘输入10,20 就不能被正确接收。,(1)抑制赋值在百分号之后
25、、转换控制字符之前加进一个星号(*)时,scanf()函数将正常读入对应的数据,但不赋值。例如,%*c将抑制一个输入的字符;%*d将抑制一个输入的整数等。例如scanf(“%d%*c%d“, 若从键盘输入10/20 则函数把10赋给a,20赋给b,而“/”被忽略。即%*c的作用是跳过一个输入字符。 (2)限制接收的字符个数在百分号和控制字符之间插进一个整数可以限制从输入数据中接收的字符个数。如果连续输入的字符个数超过指定的长度,则多余的字符被截断;反之,若连续输入的字符个数尚未达到指定的长度而提前遇到分隔符,则只接收分隔符之前的字符。,使用scanf()的几个特殊控制,2.5.3 单字符输出输
26、入函数,单字符输入输出函数getchar()和putchar()函数定义在标题文件stdio.h中,当需要进行单个字符的输入和输出时,它们比scanf()和printf()简洁。,putchar(c); 其中,c是一个字符型常量或变量,也可以是一个取值不大于255的整型常量或变量。该函数的功能是向标准输出设备输出一个字符。,1. putchar()函数,【例】 用putchar()函数输出一个字符。#include void main() int c;char d;c=65; d=A;putchar(c);putchar(d);putchar(A);putchar(65);,调用getchar
27、()函数的一般格式为:getchar();这是一个不带参数的函数,即圆括号中没有参数,但圆括号不能省略。getchar()函数的功能是从标准输入设备接收一个字符。,2单字符输入函数getchar(),【例】 用getchar()函数输入一个字符。#include void main() char c;c=getchar();printf(“%cn“,c);printf(“%dn“,c);程序运行时,等待用户从键盘输入字符,假设用户按了字母a及回车键,则屏幕显示:a (键盘输入)a (printf()函数按字符格式显示c的值)97 (printf()函数按整数格式显示c的值),注意:getcha
28、r()还可以作为putchar()的参数,例如putchar(getchar(); 其功能是显示用户从键盘输入的字符。使用getchar()函数时,回车键也作为输入字符的一部分。特别要注意在连续调用该函数时,回车键将会转换成换行符被下一个getchar()接收。例如#include void main() char c,d;c=getchar();d=getchar();printf(“%cn“,c);printf(“%dn“,d);,程序运行时,用户输入字母a及回车键后,字母a被变量c接收,而回车键将转换成换行符被变量d接收,屏幕显示为:aa (printf()函数按字符格式显示c的值)10
29、 (printf()函数按整数格式显示d的值),2.5.4 单字符输入函数,getche()和getch()用于输入单个字符而不必按回车键。getche()函数将用户输入的字符在屏幕上回显出来,getch()不回显用户输入的字符。 getche()和getch()定义在标题文件中。,【例】 #include void main() char c;c=getche();printf(“%cn“,c); printf(“%dn“,d); 程序运行时,用户只要按字母a,屏幕立即显示:aa (第一个a是用户输入的,第二个a是getche()函数回显的)a (printf()函数按字符格式显示c的值)97 (printf()函数按整数格式显示c的值)getche()把输入的字符回显在屏幕上,而getch()则不回显,这对输入密码和选择菜单特别有用。,