C语言程序设计教程
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

2.3 基本类型数据

2.3.1 整型数据

1.整型数据类型标识符

整型数据分为基本整型、短整型、长整型和无符号型4种。

① 基本整型(简称整型):类型标识符为int。

② 短整型:类型标识符为short int或short。

③ 长整型:类型标识符为1ong int或1ong。

④ 无符号型:表示不带符号的整数。

无符号型整数又可分为以下3种。

① 无符号整型:类型标识符为unsigned int。

② 无符号短整型:类型标识符为unsigned short。

③ 无符号长整型:类型标识符为unsigned 1ong。

C语言标准没有具体规定以上各类数据所占的内存字节数,不同C编译系统有不同的规定。表2.2所示为在VC++6.0编译环境中各种整型数据所占的内存字节数和取值范围。

表2.2 整型数据类型所占内存字节数和取值范围

在一个存储单元中存储一个有符号整数时,用最高位表示符号,最高位为0说明是正数,最高位为 1 说明是负数,其余二进制位表示数值,并且以二进制补码的形式表示。如果存储的是一个无符号整数,则所有二进制位都用来表示数值。例如:用两个字节存放一个短整型数时,假设两个字节的所有二进制位全部为1,如果说明为short类型,则它代表的是-1,如果说明为unsigned short类型,则它代表的是65535。

2.整型变量的定义

根据表2.2给出的整型数据类型标识符可以定义相应的整型变量。例如:

            int i,j,k;                  /* 定义变量i,j,k为整型 */
            unsigned short n,m;         /* 定义变量n,m为无符号短整型 */
            long p,l;                   /* 定义变量p,l为长整型 */

当按上述方法定义变量时,编译系统仅为所定义的变量分配了存储单元,而没有在存储单元中存放任何数据,此时的变量不能正确使用,因为变量中的值无意义。

C语言允许在定义变量的同时,对该变量预先设置初值,也称变量的初始化。例如:

            int i1=6;                /* 定义i1为整型变量并赋初值6 */

也可以为被定义变量的一部分赋初值,例如:

            int i1,i2,i3=10;

定义i1、i2和i3为整型变量,并只对i3初始化,值为10。

如果对几个变量赋以同一个初值,不能写成:

            int a=b=c=8;

而应写成:

            int a=8,b=8,c=8;

3.整型常量

整型常量简称为整数或整常数。C语言程序中整型常量有以下3种表示形式。

① 十进制整数:按通常习惯的十进制整数形式表示,例如,102、-98、0等。

② 八进制整数:以数字0开头的八进制数符串,数字0是八进制整数的前缀,八进制数符为0~7。八进制数通常是无符号数。例如,025(表示十进制数21)、0400(表示十进制数256)。

③ 十六进制整数:以0x或0X开头的十六进制数符串,0x或0X是十六进制整数的前缀,十六进制数符为0~9和a~f(或A~F),其中a~f(或A~F)对应于十进制数10~15。十六进制数通常是无符号数。例如,0x14(表示十进制数20)、0xFFFF(表示十进制数65535)。

整型数又分为长整型数、短整型数和无符号整型数。长整型数在表示上与其他整型数的区别是加后缀L或l。所谓后缀是指在数字后面加写的字母,如1234L、0X2abL等。无符号数的后缀是U或u,如7543U、0125u等。前缀和后缀可同时使用以表示不同类型、不同进制的整型数。例如,03456LU表示八进制无符号长整型数。

在程序中出现的整数根据前缀来区分各种进制数,根据后缀来区分不同类型,因此在书写常数时不要把前缀和后缀弄错造成结果不正确。

2.3.2 实型数据

1.实型数据类型标识符

实型数据有单精度型和双精度型两种。

● 单精度型:类型标识符为float。

● 双精度型:类型标识符为double。

在VC++6.0中,实型数据占内存大小、取值范围和有效数据位数如表2.3所示。

表2.3 实型数据类型占内存大小、取值范围和有效数据位数

注意:VC++6.0中,所有的float类型数据在运算中都自动转换成double型数据。

与整型数据的存储方式不同,实型数据是按照规范化的指数形式存储的。所谓规范化的指数形式是指其尾数部分为纯小数,即小数点前整数部分小于1,小数点后的第1位大于0。

2.实型变量的定义

根据表2.3给出的实型数据类型标识符可以定义相应的实型变量,并可在定义时赋初值。例如:

            float f,f1=2.5;          /* 定义f、f1为单精度实型变量,并为f1赋初值2.5 */
            double d;                /* 定义d为双精度实型变量 */

3.实型常量

实型常量即实数,又称浮点数。在C语言中实型数只有十进制形式,可以用十进制小数形式或十进制指数形式表示。

(1)十进制小数形式

一般由数字和小数点组成(必须有小数点,但小数点前后的 0 可以省略)。例如, 0.246,.246,246.0,246.,0.0等都是正确的小数表示形式。

(2)十进制指数形式

由尾数、字母e或E及指数部分组成。具体格式如下所示:

            尾数e指数部分   或   尾数E指数部分

字母e或E左边部分的尾数可以是“整数部分.小数部分”形式,也可以只有整数部分不含小数点和小数部分,或者只有小数部分前面含有小数点而不含整数部分。指数部分必须为整数,可以是正的,也可以是负的。例如,下面指数形式都是正确的:

            135e3   124e-2   -12.12e-5   .135E4   0e0

而下面的指数形式是错误的:

            e2   3.5e1.5   .e   e5   e

2.3.3 字符型数据

1.字符型数据类型标识符

字符型数据的类型标识符为char,在内存中存储一个字符型数据需要1个字节。

2.字符型变量的定义

使用字符型数据类型标识符char可以定义字符型变量,并可在定义时赋初值,例如:

            char c1,c2='A';             /* 定义两个字符型变量c1、c2 ,并给c1赋初值'A' */

3.字符型常量

C语言中,一个字符型常量代表ASCII字符集中的一个字符。在C语言程序中字符型常量有以下两种形式。

① 用一对单引号(即撇号)括起来的单个字符。例如,'b'、'Y'、'9'、'('、'y' 等都是合法的字符型常量。

② 用一对单引号(即撇号)括起来的以一个反斜杠(\)开头的转义字符,形如'\n','\t'等,意思是将反斜杠(\)后面的字符转变成另外的意义。例如,'\n'不代表字母n而是作为换行符。像换行这种非显示字符难以用一般形式的字符表示,所以C语言规定用转义字符这种特殊形式表示。常见的以反斜杠(\)开头的转义字符见表2.4。

表2.4 转义字符表

单引号是字符型常量的定界符。注意,'Y'和'y'是不同的字符型常量。

表2.4中最后两行用ASCII码(八进制数或十六进制数)表示一个字符,即它将字符的ASCII码值转换为对应的字符。例如,'\103'代表字符C,'\012'代表换行,'\376'代表图形字符■。可见,使用表2.4中的表示方法可以表示任何可输出的字母字符、专用字符、图形字符和控制字符。请注意,'\0'或'\000'代表ASCII码为0的控制字符,即“空操作”字符,它可被用在字符串中。

【例2.2】 字符型常量的输出。

程序代码如下:

            #include "stdio.h"
            main( )
            {
              printf("Hello!\thow are you?\nI\'m fine!\n");
              printf("This is a cup\b\b\bpen.\n");
              printf("A,\101");
            }

该程序中3次调用printf( )函数,直接输出双引号内的各个字符。请注意其中的转义字符。第1个printf( )函数先从第一行左端开始输出“Hello!”,然后遇到“\t”,它的作用是跳格,即跳到下一个输出位置,在所用系统中,一个输出区占8列。下一输出位置从第9列开始,故从第9列开始输出“how are you?”。下面遇到“\n”,代表回车换行,返回到下一行最左端(第1列),输出字符“I”,然后遇到“\'”,表示输出“'”,接着输出“m fine”。下面是“\n”,作用是“回车换行”,即光标被移到下一行第一个字符位置。

第2个printf( )函数先输出字符“This is a cup”,后面遇到3个“\b”,“\b”的作用是“退一格”,因此“\b\b\b”的作用是使当前输出位置回退3格到“c”的位置,接着输出“pen.”。最后是“\n”,即“回车换行”。

第3个printf( )函数先输出“A,”,然后遇到“\101”,它的作用是输出ASCII码(八进制数101)所对应的字符,即“A”字符。

程序运行后在显示屏上最后看到的结果是:

            Hello!  how are you?
            I'm fine!
            This is a pen.
            A,A

注意:2次调用printf( )函数时,先输出“This is cup”,退3格后再输出“pen.”,“pen.”将取代原来的“cup”。程序执行时在屏幕上看不到“cup”。实际上,屏幕上完全按程序要求输出了全部的字符,只是因为在输出前面的字符后很快又输出后面的字符,在人们还未看清楚之前,新的字符已取代了旧的字符。

4.字符型数据在内存中的存储形式

字符型变量存放一个字符,实际上并不是把该字符本身存放到内存单元中去,而是将该字符的ASCII码(ASCII码对照表见附录C)存放到存储单元中。例如,字符'A'的ASCII码为65,'\n'的ASCII码为10,则程序段:

            char c1,c2;
            c1='A';c2='\n';

执行后,在内存中变量c1和c2的值如图2.3所示。

图2.4 3 字符型数据的存储

因为在内存中,字符数据是以ASCII码的形式存储的,它的存储形式与整数的存储形式类似。因此,在C语言中,字符型数据可以与整型数据混合使用。C语言允许对整型变量赋予字符值,也允许对字符变量赋予整型值。一个字符型数据既可以以字符形式输出,也可以以整数形式输出。以字符形式输出时,需要先将存储单元中的ASCII码转换成相应的字符,然后输出。以整数形式输出时,直接将ASCII码作为整数输出,也可以对字符数据进行算术运算,此时相当于对它们的ASCII码进行算术运算。

【例2.3】 字符型数据的输出。

程序代码如下:

            #include "stdio.h"
            main( )
            {
              char c1;                          /* 定义c1为字符型变量 */
              c1=65;
              printf("%c,%d\n",c1,c1);         /* c1以字符型和整型两种格式输出 */
            }

程序运行结果为:

            A,65

该程序中c1被定义为字符变量。但在第5行中,将整数65赋给了c1,就是将整数65直接存放到c1的内存单元中。程序的第5行也可用以下语句等价代替:

            c1='A';

该语句在执行时,系统首先要将字符'A'转换成其对应的 ASCII 码值 65,然后再存放到cl的内存单元中。二者作用是相同的。第6行将按字符型和整型两种格式输出变量c1的值。其中“%c”是输出字符的格式符。“%d”是输出整数的格式符。有关输出数据的格式符详见第3章。

注意:字符型数据只占一个字节,所以它只能存放0~255范围内的整数。C语言对字符型数据的这种处理增加了程序设计的自由度和灵活性。例如,实现英文字符的大小写转换、数字字符和数字的相互转换等就变得非常方便。

【例2.4】 编写程序实现英文字符的大小写转换。

分析:因为英文字母大小写之间的ASCII码值相差32(参见附录C),即a'-'A'=32,所以很容易通过C语言程序实现英文字符的大小写转换。

程序代码如下:

            #include "stdio.h"
            main( )
            {
                char c1;
                c1='a';
                printf("%c,%c\n",c1,c1-32);
            }

程序运行结果如下:

a,A

【例2.5】 编写程序实现数字字符和数字的相互转换。

从附录C可以看出,数字字符0的ASCII码值为48,数字字符1~9的ASCII码值为49~57,可以很容易地实现数字字符和数字的相互转换。程序代码如下:

            #include "stdio.h"
            main( )
            {
                char c1,c2;
                c1='1';
                c2=49;
                printf("%c,%c\n",c1,c2);
                c1=c1-'0';
                c2=c2-'0';
                printf("%d,%d\n",c1,c2);
            }

程序运行结果如下:

            1,1
            1,1

注意:程序运行后,第1printf语句输出的是两个字符1,而第2printf语句输出的则是两个数字1。请大家思考,如果把这两条语句互换位置,结果会是什么?

2.3.4 字符串常量

字符串常量是由一对双引号(" ")括起来的字符序列。双引号是字符串常量的定界符。在组成字符串的字符序列中若有双引号时应使用转义字符“\"”来表示。字符串的长度为字符序列中字符的个数,不包括两边的双引号。

例如:

            "It is fine day."          /* 长度为15 */
            "12345678.09"              /* 长度为11 */
            "$10000.00"                /* 长度为9 */
            ""                         /* 引号中有一个空格,长度为1 */
            ""                         /* 引号中什么也没有,长度为0 */
            "a"                        /* 引号中有一个字符a,长度为1 */

因为字符串长度的不确定性,所以字符串常量在内存中存储时,系统自动在每个字符串常量的尾部加一个字符串结束标志字符“\0”(“\0”是一个ASCII码为0的“空操作”字符,它不引起任何控制动作,也不是一个可显示的字符),以便系统据此判断字符串是否结束。前面已提到,在内存中存储单个字符需要1个字节,因此,长度为n的字符串常量,在内存中要占用n+1个字节的存储空间,前n个字节存储组成字符串的n个字符,最后1个字节存储字符串结束标志“\0”。

例如,"hello"在内存中的存储形式是(字符对应的ASCII码值):

为了能直观理解,以后表示字符时,直接用字符本身表示,则上例表示成:

注意:字符串结束符'\0'是系统自动加上的。在输出一个字符串时,字符串结束符并不输出,例如:

            printf("hello");

执行此语句时从左到右一个字符一个字符地输出,直到遇到最后的'\0'字符,表示字符串结束了,停止输出。另外,在书写字符串时也不必加'\0',否则就会画蛇添足。

了解了这一点,就可以理解字符串常量"b"和字符型常量'b'的区别了。

存储字符型常量'b'只需要1个字节:

存储字符串常量"b"需要2个字节:

在C语言中没有专门的字符串变量,如果希望将一个字符串存放在变量中,就要使用字符数组的概念,字符数组中的每一个数组元素存放一个字符。有关字符数组的知识详见第8章。