c语言中的基本数据类型有
- int 定义整形变量
- float 定义浮点型变量(浮点型就是保存小数的)
- double 定义双精度浮点型变量
- char 定义字符型变量
整形变量
整形变量自然就是保存整数的变量。为什么要把整数和小数分开呢?
这是因为,在二进制中,只有0和1,没有小数点,因此整数和小数在计算机看来,都是1和0的组合,没有什么区别。
而我们把某一块数据看作小数,那么他就是小数,把它看作整数,他就变成了整数。
因此一个数据是什么类型都是看你用什么标准去看他。
整形变量只能保存整数,如果你让他保存一个小数会怎么样呢。让我们将他作为一个问题,稍后我们会做相关的实验来进行探究。
浮点型
浮点型就是保存小数的类型,那么为什么有float和double之分呢?
前面说到过,变量的本质就是内存上的一小块储存空间。
而空间的容量是有限的,就像一个瓶子,当你装满了水后就放不下其他东西了。(别告诉我水里面还能继续溶解气体。。。)
想要装更多东西?没关系,方法就是增大容积(增加内存上储存空间的大小)。
但是很不幸,c语言中,一个类型所占用的空间是固定的(尽管不同的环境下变量的空间确实有可能不同,但是在一个确定的环境下各种类型的空间大小就是一个常 数!)。这意味着我们不能像往气球里面灌水一样(我打赌你玩过),气球的体积会自动增大。我们只能换一个更大的杯子来装水。
float和double就是两个不同的杯子。
double有双的意思,而在编程中,double的储存空间便是float的两倍。空间更大他的精度自然更大。
那么你可能又会问了,既然double精度更高,那么留着float干啥呢?
当然是省空间了,在早期,计算机的内存是很少的,现在早已淘汰的512M内存在当时是不敢想象的。
现在计算机的内存变大了,我们当然不用再去挖空心思的去想如何省内存。不过现在某些单片机上硬件内存仍然很紧张。例如很常用的51单片机上,只有218B的RAM,请注意是B不是MB也不是KB,在这种环境下省内存的意义便体现出来了。
字符型
字符型就是用来保存字符的了。
这里有一点需要注意,那就是字符是如何保存的?
前文中已经说过很多遍,计算机内只有1和0两个符号,那么如何表示各种各样的字符呢。
把某个数据看作是字符就行了。
我们可以规定,1代表a,2代表b,自然3就是c,4就是d
现在就好办了,只要一个专门负责显示的程序,遇到1就将a显示出来,遇到2则显示b,依次类推。此时,我们其实已经自己创造了一种数与字符的对应关系,也就是编码。
很不幸的是,我们现实中的计算机中并不是使用上面的字符和数字映射的关系,尽管它看起来比较简单。
我们使用的是一种叫做ASCII的编码方案(American Standard Code for Information Interchange,美国信息互换标准代码)。如果你要问为什么前面有个American?答案很简单,因为计算机一开始就是美国人发明的。
注意ASCII的最后是两个大写的“i”而不是两个小写的“L”
关于ASCII的更多内容,我们将在专门的一节说道。
有符号和无符号
一般来说,数值可以分为有符号和无符号两种,有符号就是要区分数据的正负,而无符号则不需要考虑数据的正负,它通常用在那些不关心正负或者根本就没有负数情况的场合。比如计算圆的面积,你总不可能找个面积为负数的圆吧!
我们使用unsigned来修饰无符号类型,而用signed来修饰有符号的变量。
如 unsigned int, signed double等
其实int,float和double已经被规定了是默认有符号的,即int=signed int,double=signed double。
你可能已经意识到,上面遗漏了一个char,这当然不是不小心写漏了。而是人们并没有专门的去规定它是不是有符号的,即char 可能等于signed char,也可能等于unsigned char,具体要看编译器的心情。不同的环境是有不同的结果的。
有符号和无符号的区别不仅仅在于无符号不能保存负数。要讨论这个问题我们需要先从数据在内存中保存的方法说起。
任何数据在电子计算机中都是使用二进制保存的,而保存数据的空间是有限制的,以char为例,他是一个字节。也就是8位。
比如 0111 1111
因为二进制中没有负号这个东西,如果需要保存数据的正负呢,你可能已经想到,我们可以用一位的0和1来表示这个数的正负。恭喜你,你猜对了!人们规定将最高位用来说明数据的正负(也就是上面的0),用1代表负数,而0则表示正数。这样看来,我们只有剩下的7位来保存数值了。
但是有时候我们不需要考虑数据的正负,这样最高位就没有意义了,我们总不能空着它不用吧!为了节约空间,在不考虑正负的情况下,我们便将最高位也用来保存数据。这样一来,无符号保存数据用了8位,而有符号则只有7位。空间不同它们所能保存数据的范围自然不同。
signed char是-128~127,你可能会问,为什么正数只到127,因为还有一个0呀!
unsigned char则是0~255.
int在32位环境下一般是4字节,所能表示的数据范围是-2147483648 ~ +2147483647,这个范围有时候稍微大了一点,比如我的某个数据只会在0-10000中变化,还用4字节来保存就显得有些浪费了。
于是在基本数据类型之下,我们还定义了一些修饰符。它们是:
short和long,取字面意思,short就是短,long就是长。
它们可以这样写:
short int, long int, long double
short int顾名思义就是短整型了。至于short double?那不就是float嘛
然后int在这个时候可以省略,也就是说short=short int,long=long int
不过double就不能省略了。
人们并没有规定short一定是多长,只要不比int大就行,long也是这样,不能比int小。
我们可以用下面这个程序来测试一下,各个数据类型的大小和范围
#include <stdio.h> #include <stdlib.h> #include <limits.h> #include <float.h> int main() { printf("char>%d Byte %d ~ %d\n\n", sizeof(char), CHAR_MIN, CHAR_MIN); printf("unsigned char>%d Byte %d ~ %d\n\n", sizeof(unsigned char), 0, UCHAR_MAX); printf("int>%d Byte %d ~ %d\n\n", sizeof(int), INT_MIN, INT_MAX); printf("unsigned int>%d Byte %d ~ %u\n\n", sizeof(unsigned int), 0, UINT_MAX); printf("short>%d Byte %d ~ %d\n\n", sizeof(short), SHRT_MIN, SHRT_MAX); printf("long>%d Byte %ld ~ %ld\n\n", sizeof(long), LONG_MIN, LONG_MAX); printf("float>%d Byte %e ~ %e\n\n", sizeof(float), FLT_MIN, FLT_MAX); printf("double>%d Byte %e ~ %e\n\n", sizeof(double), DBL_MIN, DBL_MAX); return 0; }
请自己编译并运行程序
可以看到在gcc环境下,char默认是有符号的!