数据和C

时间:2023-02-04 16:56:15

计算机设计的初衷就是用来计算,由此也可看出,数据的输入、输出是必不可少的步骤,也是最关键的,随着计算机的发展,计算机能够完成各种任务,而把数字、字母和文字输入计算机,就是希望它能够利用这些数据完成我们预期的设想。

C语言提供两大系列的多种数据类型,即整数类型和浮点类型,就是我们日常生活中的整数和小数,下面将介绍如何声明它们,除此之外,还将介绍常量和变量的区别。

一. 整数类型

C语言提供了许多整数类型,为什么一种类型不够用?因为C语言让程序员针对不同情况选择不同的类型。特别是,C语言中的整数类型可表示不同的取值范围和正负值。一般情况下使用int类型即可,但是也根据实际情况,选择其它类型。

int类型是有符号整型,即int类型的数值必须是整数,可以是正整数、负整数或零。ISO C规定int的取值范围最小为-32768—32767,一般而言,系统用一个特殊位的值表示有符号整数的正负号,在学计算机组成原理的课程中,在讲到数据的存储时,会介绍相关内容。

1.int变量

在前面的C语言概述中,我们已经声明过int型变量,在创建了变量之后,变量如何获得值?有三种途径,第一种途径是赋值:

int num;
num = 1;

第二种途径是通过函数(如:scanf()函数)获得值;而第三种途径则是初始化变量,在声明的同时对变量进行赋值:

int hogs = 21;
int cows = 42, goats = 56;
int dogs, cats, chicken = 6; //可以,但不太好,可能导致误解,尽量将初始化的变量和未初始化的变量放在不同的声明中。
2.int常量

如前面出现的整数1,21,42等等。C语言把不含小数点和指数的数作为整数,所以像21.0,2.1E1都不是整数。如果要输出整数,可以根据需要选择不同的进制输出,以十进制显示数字,使用%d;以八进制显示数字,使用%o,如果要显示八进制的前缀0,就要使用%#o;以十六进制显示数字,使用%x,如果要显示十六进制的前缀0x或0X,就要使用%#x或%#X。

3.其它整数类型

C语言提供3个附属关键字修饰基本整数类型:short、long和unsigned。

short int可简写为short,C语言规定short占用的内存要小于int,一般是占用两个字节,常用于数值较小的场合使用,以节省空间;long int简写为long,C语言规定long占用内存的大小只要大于等于int即可,用于数值较大的场合,一般占用4个字节或8个字节;为了适应现在普遍64位处理器的计算机,才引入long long类型,long long int简写为long long适用于更大数值的场合,该类型至少占用8个字节。不规定类型占用整数类型的具体内存大小,是为了适应不同的机器。

unsigned int和unsigned只用于非负值场合,这种类型表示无符号整数,如:16位的unsigned int允许的取值范围是0—65535,而不是-32768—32767,这是由于其中一个不作符号位二十数值位,因此unsigned int比int的最大值大了一倍,同理unsigned可用在其它整型前;在任何有符号类型前面添加关键字signed,可强调使用有符号类型的意图,像short、short int、signed short、signed short int都表示用一种类型。

在C90标准中添加了unsigned long和unsigned short类型,C99标准又添加了unsigned long long和long long类型,值得注意不是所有C编译器都能识别这些声明。

4.使用多种整数类型的原因

主要还是实际应用需要,如int类型的范围最少为-32768—32767,如果数据范围只是0—10000,显然用short int类型更合适,像更长范围的long int类型引入就更加显然了,当数据范围到了1010以上时,int类型已经无法表示(只要绝对值在109以内都能定义为int),而现在计算机普遍使用64位处理器,所以后面又引入了long long类型。C标准对基本数据类型只规定了允许的最小大小,int类型那么多,应该如何选择?首先考虑unsigned类型,这种类型的数通常用来计数,因为计数不考虑负数,而且能表示更大的整数。

注:现在个人计算机最常见的设置是long long占64位,long占32位,short占16位,int占16位或32位(依据计算机的自然字长而定)。

这里给两点建议,当long类型和int类型占用空间相同时,使用long类型,这样移植到别的机器上时仍能正常运行;当int设置为32位时并且需要使用16的值时,应使用short类型以节省空间,当然只有当程序使用的空间相较于系统可用内存较大时,才需要重点考虑节省空间的问题,而使用short类型的另一个原因是,计算机中某些组件使用的硬件寄存器是16位,机器运算效率更高,只需传送一次数据就可。

5.整数类型的打印

打印unsigned int类型的值,使用%u转换说明;打印十进制、十六进制、八进制分别使用%d、%x、%o,打印short、long、long long类型分别使用%h、%l、%ll前缀,再加上要打印的进制数,如打印short类型,以八进制形式输出:%ho;若要打印无符号,如%lld和%llu分别表示有符号和无符号类型。对于无符号整数当输出达到它能表示的最大值时,会从起始点开始,如

unsigned short num = 65535;
printf("%hu %hu %hu", num, num+1, num+2);

分别会输出为32767,0和1。

二. 使用字符char类型

char类型用于存储字符,但是实质上,char是整数类型,因为char类型实际上存储的是整数而不是字符。计算机用数字编码来处理字符,即用特定的整数表示特定的字符,常用编码如ASCII编码,标准ASCII码的范围是0—127,只需要7位即可表示,而char类型有8位存储单元,

char grade = 65; //对于ASCII编码,没有问题,但这不便于移植
char grade_B = 'B';

对于第一条代码,前提是系统使用ASCII编码,若用'A'来表示65更为稳妥,代码可移植性更好,因此最好使用字符常量,而不是数字代码值。奇怪的是,C语言将字符常量视为int类型而不是char类型,对于第二条代码,本来字符常量'B'对应的数值是66存储在32(16)位存储单元中,现在却可以存储在8位的存储单元中,利用字符常量这个特性,我们可以声明一个字符常量'FATE',即把4个独立的8位ASCII码存储在一个32位(假设(int)为32位)的存储单元中,只有最后8位有效,因此,grade的值是'E'。

char ch = 'FATE';
printf("%c", ch);

当我们查看ASCII表时,我们会发现有些ASCII字符打印不出来,能打印出来的都是字符、数字和标点符号,对于那些打印不出来的ASCII字符,我们能够使用ASCII码,

char beep = 7; //蜂鸣字符

更为实用的是第二种,使用转义字符\,下面是转义序列表:

\a

警报

\'

单引号

\b

退格

\"

双引号

\f

换页

\?

问号

\r

回车

\\

反斜杠\

\n

换行

\0__

八进制值

\t

水平制表符

\x__

十六进制值

\v

垂直制表符



下面简单分析以下转义序列,警报字符\a,蜂鸣是最常见的警报,能否产生听到或看到的警报取决于计算机硬件,C标准规定警报字符不得改变活跃位置(活跃位置就是光标位置,即下一字符将出现的位置),所以产生的效果就是发生一声蜂鸣警报,但不会移动屏幕光标;接下来的\b、\f、\r、\n、\t、\v是最长用的输出设备控制字符,当然这些并不一定在所有的显示设备上都起作用,像换页符和垂直制表符在PC屏幕上会产生奇怪的符号,光标并不会移动,只有将其输出到打印机上时才会产生前面描述的效果;接下来的三个转义序列\'、\"、\\用于打印'、"、\,由于这三个字符直接使用会影响输出函数printf()的输出效果;对于最后面两个转义序列是ASCII码的特殊表示,感兴趣可以自行了解,建议不使用这种方法,直接使用转义序列\a不仅好记而且可移植性更高。

有的编译器将char类型实现为有符号类型,这意味着char可表示的范围是-128—127,而有的编译器将char类型实现为无符号类型,那么char可表示的范围是0—255。根据C90标准,C语言允许在关键字char前面是signed或unsigned,这样无论编译器以何种方式实现char都没有影响。

三. _Bool类型

C99标准添加了_Bool类型,用于表示布尔值,即逻辑值true和false。因为C语言用1和0表示true和false,所以_Bool类型实际上也是一种整数类型,而且对于0或1而言,1位的存储空间足够了。

四. 可移植类型

扩展的整数类型,C99新增了两个头文件stdint.h和inttypes.h,以确保C语言的类型在各系统中的功能相同。

五. 浮点型

C语言中的浮点数类型有float、double和long double类型。

C标准规定,float类型必须至少能表示前6位有效数字(一般是6-7位),并非精确到小数点后6位数字,如:

float f_num = 3.23456789;
printf("%f", f_num); //得到的结果是3.234568,第七位数字不精确,这里可能各个运行的情况有所不同

且取值范围至少是1.0e-37—1.0e37。通常系统存储一个float类型要占用32位,其中8位用于表示指数的值和符号,剩余24位用于表示尾数,即浮点数的表示。

double类型最小取值范围与float相同,但至少能表示10位有效数字(一般是15-16位)。一般情况下,double类型占用64位存储空间,一些系统将多出来的32位全都用来表示尾数,另一些系统将其中一些位分配给了指数部分,以表示更大的范围,无论哪种方法,double类型的值至少有13位有效数字。超过了标准的最低尾数规定。

第三种浮点类型long double,以满足比double类型更高的精度要求。不过C只保证long double类型至少与double类型的精度相同。

通常,系统默认浮点数常量是double类型的精度,如下面的4.0就是double类型,使用双精度进行乘法运算,然后将乘积截断成float类型的宽度。打印long double类型时,要使用%Lf,%Le或%La转换说明。

float f_num = 4.0 * 2.0;

C99标准添加了一种新的浮点型常量格式,感兴趣可自行了解,这里简单叙述以下,在十六进制数前加上十六进制前缀0x或0X,用p或P分别代替e和E,用2的幂代替10的幂(即,p计数法),如:0Xf2e.abc8p8,它表示的十进制值是(15*16^3+2*16^2+14*16^1+10/15+11/256+12/4096+8/65536)*2^8。用%e表示以e计算法打印浮点数,用%a表示以十六进制的格式打印浮点数。

六. 复数和虚数类型

许多科学和工程计算都要用到复数和虚数。C99标准支持复数类型和虚数类型。C语言有3中复数类型:float _Complex、double _Complex、long double _Complex,对于float _Complex类型的变量应包含两个float类型的值,分别表示复数的实部和虚部。类似的,C语言的3中虚数类型:float _Imaginary、double _Imaginary、long double _Imaginary。如果包含complex.h头文件,就可去掉下划线_,还可用I代替-1的平方根,否则不能这样做。

七. 其它类型

C语言还有一些由基本数据类型衍生的其它类型,包括数组、指针、结构和联合。

八. 小结

1.基本数据类型用到的关键字:

char、short、int、long、float、double、unsigned、signed、_Bool、_Complex、_Imaginary。

2.有符号整型:

short或short int—最大的short类型整数小于或等于最大的int类型整数。C语言规定short类型至少占16位,一般是2B。

int—系统给定的基本整数类型。C语言规定int类型不小于16位,一般是4B,推荐大家自己用编译器查看各类型占用存储空间大小,sizeof(int)。

long或long int—该类型可表示的整数大于或等于最大的int类型整数。C语言规定long类型至少占用32位,一般是4B。

long long或long long int—该类型可表示的整数大于或等于最大的long类型整数。C语言规定long类型至少占用64位,一般是8B。

3.无符号整型:

用unsigned前缀即可,单独的unsigned相当于unsigned int。

4.字符类型:

可打印出来的符号都是字符。,char类型的一个字符占用一个字节,1字节通常是8位,但是如果要表示基本字符集,也可以是16位或更大的位数(2^n)。

5.布尔类型:

布尔类型_Bool是无符号的int类型,可用1表示true,0表示false。

6.实浮点型:

float—系统的基本浮点类型,可精确表示至少6位有效数字。

double—至少能精确表示10位有效数字,一般是15-16位。

long double—能比double表示更多的有效数字和更大的浮点数范围。

7.复数和虚数浮点数:

复数的实部和虚部类型都基于实浮点类型来构成;虚数类型是可选的类型。