基本数据类型
数据是程序加工、处理的对象。这些数据对象一般会被划分为一些集合。属于同一集合的各数据对象具有同样的性质,可以对它们进行同样的操作、编码及存储。具有这样性质的数据集合称为数据类型。所有程序语言都是用数据类型来描述程序中的数据结构、数据表示范围、数据在内存中的存储分配等。C语言的数据类型可分为四大类:基本类型、构造类型和指针类型和空类型。见下图所示:
整型
基本类型 浮点型
字符型
数组类型
结构体类型
C语言数据类型 构造类型 联合体类型与共用体类型
枚举类型
指针类型
空类型
本章主要介绍基本数据类型。其它数据类型将在以后的章节做全面的介绍。
2.4.1 整型
C语言提供基本整数类型int,为了扩大C语言中基本整数类型的使用范围,C语言还提供4种类型修饰符:
long 长型
short 短型
signed 有符号型
unsigned 无符号型
其中修饰符signed表示有符号数,如果既没有指定signed也没有指定unsigned,则默认为有符号数signed。也就是说signed是完全可以不写的。
因此C语言扩充出6种整数数据类型,
有符号基本整型 [signed] int
无符号基本整型 unsigned [int]
有符号短整型 [signed] short [int]
无符号短整型 unsigned short [int]
有符号长整型 [signed] long [int]
无符号长整型 unsigned long [int]
这些不同类型的差别就在于采用不同位数的二进制编码方式,占用不同大小的存储空间,就会有不同的数值表示范围。表2-2列出了ANSI C标准定义的整数类型和有关数据。
整数类型 | 存储字节 | 二进制位 | 最小取值范围 |
有符号基本整型[signed] int | 2字节 | 16 | -32758~32767 |
有符号短整型 [signed] short [int] | 2字节 | 16 | 同int |
有符号长整型 [signed] long [int] | 4字节 | 32 | -2147483648~2147483647 |
无符号基本整型unsigned [int] | 2字节 | 16 | 0~65535 |
无符号短整型 unsigned short [int] | 2字节 | 16 | 同unsigned int |
无符号长整型(unsigned long [int]) | 4字节 | 32 | 0~4294967295 |
表2-2常用的基本整数类型
C语言标准本身并不限制各种类型数据所占的存储字节数,上表中给出的是最小取值范围,表示不能低于此值。例如在有的C编译系统中,基本整型占4个字节。TURBO C中的规定与上表相同。
计算机内部采用二进制补码形式表示一个整型数据。由于不同整型所能表示的数据范围不同,因此在程序中要注意整型数据的数据溢出问题,下面举例说明。
例 2.2 编写求两数和的C程序并上机运行。程序如下:
/* sum.c源程序*/
#include <stdio.h>
void main(void)
{ int a , b , c;
a=32767;
b=1;
c=a + b ;
printf("c=%d\n", c);
}
实际运行结果如下:
c= -32768
显然结果不是读者想象的32768,为什么会出现这种情况呢?下面分析一下程序运行时变量a,b,c的存储情况和计算的过程:
0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
变量a
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
变量b
变量a加b实际上是上面两个二进制数的加法运算,得出结果如下
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
变量c
变量c中的二进制数是-32768的补码形式。出现错误的原因是因为a+b的值已经超过了int类型所能表示的数据范围。可见在程序中合理定义变量的数据类型是非常重要的。
程序可更正如下:
#include <stdio.h>
void main(void)
{ long a , b , c;
a=32767;
b=1;
c=a + b ;
printf("c=%1d\n", c);
}
此时程序运行结果为:
c=32768
可见在程序设计时给变量选择合适的数据类型是非常重要的。
2.4.2 字符型数据char
表示字符类型变量的关键字是char,定义字符型变量的形式是:
char 变量名表;
例如:
char c1,c2;
表示定义变量c1和c2,它们都是字符型的变量。一个字符型变量所占用的内存空间通常为一个字节,即8位。就是说,一个变量中只能存放一个字符,不能把一个字符串赋给一个字符变量。
当把一个字符常量赋给一个字符变量时,该字符变量的值就是相应字符的编码值。例如:
char c;
c=′a′;
C语言中的字符型可以和整型数据是通用的,例如c+1、’a’-2在C语言中是合法的运算。但是要注意字符型只占1个字节,它可表示的整数要比基本整型小的多。而且字符数据的最高位是否作为符号位要由具体实现规定,例如TURBO C中的char类型就被看作是有符号的整数,取值范围-128~127。
在ANSI C和ISO C中,还规定了signed和unsigned两种修饰符可用于char类型。即为signed char型和unsigned char两种类型,前者是有符号字符型,后者是无符号字符型。
例2.3 字符运算
#include <stdio.h>
void main(void)
{
char x,y;
x=′a′+10;
y=′z′-8;
printf("%c=%d , %c=%d\n", x , x , y , y);
}
运行结果为:
k=107,r=114
分析:已知在ASCII字符集中,字母a的值为97。故变量x的结果为97+10=107,同理字母z的值为122。变量y的结果为122-8=144。在输出时要求以字符形式和十进制整数形式输出。而在ASCII字符集中编号107和122分别对应小写字母k和r。
程序中%c输出char 类型数据,%d输出 int 类型数据。
2.4.3 浮点型
在C语言中,表示基本浮点类型的关键字是float。定义一个基本浮点型变量的形式是:
float 变量名表;
例如,
float f1,f2;
这里的浮点类型是一般常说的单精度类型。除此之外,C语言中还提供其他两种浮点类型:double和long double,分别称作双精度类型和长双精度类型。float型量的取值范围是double型量的子集,而double型量的取值范围又是long double型量的子集。所有浮点型量的取值范围又都是实数集合中的一个子集。表2-3中列出了浮点型的取值范围和精度。
浮点类型 | 存储字节 | 二进制位 | 取值范围 | 精度 |
单精度型(float) 双精度型(double) 长双精度型(long double) | 4字节 8字节 16字节 | 32 64 128 | -10-38~1038 -10-76~1076 -10-152~10152 | 6位有效数字 12位有效数字 24位有效数字 |
表2-3浮点数
为了保持运算精度,在运算时所有的float型量都被转换成double型。
由于实数存储时占用有限的存储单元,有效数字也有限制。因此使用时存在舍入误差。
2.4.4 不同类型数据的混合运算
在编写程序的时候,往往会遇到不同类型的数据进行运算的问题。当不同类型的变量在运算符的作用下进行运算,就要进行类型的转换。分两种情况说明:
(1)自动类型转换
在C语言中,整型、实型和字符型数据间混合运算时没有特别指定,将按照系统默认的规则进行自动转换。即如果一个运算符两侧的操作数的数据类型不同,则系统按“先转换、后运算”的原则,首先将数据自动转换成同一类型,然后在同一类型数据间进行运算。转换规则如图2-2所示。
注意图中横向向左的箭头,表示必须的转换。char和short 型必须转换成 int 型,float型必须转换成double型。纵向向上的箭头,表示不同类型的转换方向。
例如,int型与double型数据进行混合运算,则先将int型数据转换成double型,然后在两个同类型的数据间进行运算,结果为double型。
两个float类型的数据相加,两个float也要先转换为double类型的,然后再完成加法运算。
注意:箭头方向只表示数据类型由低向高转换,即将存储长度短的数据类型转换为存储长度长的数据类型。
例如一个int类型数据和一个double类型数据混合参加运算,不要理解为int型先转换成unsigned型,再转换成long型,最后转换成double型。
例如:
3.45+’a’-5*6
运算时,第1步计算3.45+’a’,先把’a’转换为double类型的,即97.0和值为100.45;第2步计算5*6,乘积为30;第3步,计算100.45-30,先把30转换为double类型,在完成减法运算,结果为70.45,是double类型
(2)强制类型转换运算符
除自动转换外,C语言也允许强制转换。有时在程序中需要用到将存储长度长的数据类型转换为存储长度长的数据类型后再参与运算,此时就需要使用强制类型转换运算符。
有关强制类型转换运算符的具体内容参见2.6.9节。