1. 概述
类型这个概念并不陌生,就是对一种事物按照共同的特征进行分类。数据类型就是按照数据所共有的特征来分类,C编译器根据不同的数据类型来处理数据。C语言中规定,每一种数据都必须有相对应的类型。
在C语言中,基本数据类型分为三种:整数型(int)、浮点数型(float、double)、字符型(char)。复杂数据类型都是基于基本类型构建的,在后面会有单独的章节。
2. 符号修饰符signed,unsigned
学习类型之前,先看一下这两个关键字(附录中查看):signed和unsigned,在类型前加上signed关键字表示有正负号,可以是正值、负值、0,称为有符号;若使用unsigned关键字修饰,则只能表示非负数,即0和正值,称为无符号。也就是说,signed修饰的类型范围是负的最大值到正的最大值,而unsigned修饰的类型范围则是从0到正的最大值。
一般情况下,数据类型都默认使用signed修饰,就是说可以包含负值,比如定义一个整型int类型变量,如果不显示地指定符号修饰符,等同于signed int,平时使用时可以不写signed:
int a;//定义一个整型变量a
signed int a;//等同于int a
当然,有非负整数的需求,想要表示整数的值会更大,那就使用unsigned关键字修饰,int可以省略:
unsigned int a = 5;//定义一个无符号int类型a,且值为5
unsigned a = 5;//省略掉int的写法
C语言规定,signed和unsigned也可以修饰字符类型char,由系统决定默认是有符号还是无符号:
char ch;//由系统决定,可以是signed,也可以是unsigned
signed ch;//有符号字符型,-128 - 127
unsigned ch;//无符号字符型,0 - 255
C语言中,不能修饰浮点数类型,即在float和double类型前不能使用signed和unsigned,这是由于浮点数类型的值第一位就是符号位;也不能修饰布尔类型,布尔类型的值一般为0和1:
signed float f;//错误,不能修饰float
signed double d;//错误,不能修饰double
signed bool b;//错误,不能修饰bool
3. 整数类型
3.1 int关键字
C语言规定,int关键字用来表示整数型数据,int类型所表示的数据值大小是由所在的机器字长决定的,一般为4个字节(32位)或2个字节(16位)、8个字节(64位),下面是定义一个int类型的变量:
int a = 1;//定义一个int类型的变量a,且值为1
C语言中的整数默认表示的值是十进制,如果想表示为二进制、八进制和十六进制,需要在数值前加上不同的前缀字符,可以使用专门的进制计算器验算:
二进制数(Binary),简写为B或BIN,使用前缀0b或0B表示:
int a = 0b1001;//二进制数,等于十进制数9
int a = 0B1000;//二进制数,等于十进制数8
八进制数(Octal),简写为O或OCT,使用前缀0表示:
int a = 047;//八进制数,等于十进制数39
十六进制数(Hexadecimal),简写为H或HEX,使用0x前缀或0X前缀,或者后缀h或H来表示:
int a = 0xAA;//十六进制数,等于十进制数170
int a = 0XAB;//十六进制数,等于十进制数171
int a = ACh;//十六进制数,等于十进制数172
int a = ADH;//十六进制数,等于十进制数173
虽然说可以使用不同的进制来表示,但是值都是一样的。在计算机中,所有的数值都是以二进制的形式存储的,即0和1,所以使用不同的进制表示都可以,还可以参与运算。
3.2 其他int类型
在C语言中,不止int一个整型,它更像是一个中和值。如果我们还有对数据值更大的需求或者更小的需求,那么int类型就不是很合适了。对于更小的整数值,使用int存储浪费空间,对于更大的整数值,使用int存储不够。所以C语言标准基于int类型又提供了三个其他整数类型,更加灵活地控制范围:
- short int:简写为short,也称为短整型,比int占用空间更小
- long int:简写为long,也称为长整型,占用空间不能小于int
- long long int:简写为long,也成为超长整型,是整型里最大的,一般为8个字节
下面是这三种类型的声明:
short int a;
long int a;
long long int a;
还有一种书写形式,省略int关键字也可以表示:
short a;
long a;
long long a;
和int类型一样,默认情况下short int、long int、long long int这三种类型也都是有符号的(signed),当然signed也可以省略,也可以使用unsigned关键字修饰为无符号整数:
unsigned short int a;//声明无符号短整型变量a
unsigned long int a;//声明无符号长整型变量a
unsigned long long int a;//声明无符号超长整型变量a
//下面是省略int的写法,都是合法的
short a;
unsigned short a;
long b;
unsigned long b;
long long c;
unsigned long long c;
3.3 定义指定类型
上面说的定义方式都是字面量赋值,可以通过加后缀的方式来指定不同的类型。
在变量值后面加上后缀L或者l,编译器会自动存储为Long类型:
int a = 10L;//long类型
int a = 10l;//long类型,避免混淆,建议使用大写的L
int a = 047L;//八进制的long类型
int a = 0xAA;//十六进制的long类型
加上LL或者ll后缀,就指定为长整型,即Long Long int类型:
int a = 10LL;//Long Long int类型
int a = 10ll;//Long Long int类型,避免混淆,建议使用大写的L
也可以指定为无符号整数类型(unsigned int),在变量值后面加上后缀U或者u:
int a = 10U;//unsigned int类型
int a = 10u;//unsigned int类型
L后缀和U后缀可以结合起来使用,指定为unsigned long类型,L和U的顺序无关:
int a = 10LU;//unsigned long类型
int a = 10UL;//unsigned long类型
3.4 整型的极限值(表示范围)
C语言中,可以引入标准库limits.h头文件来设置类型的最小值和最大值,limits.h头文件决定了各种变量类型的各种属性,规定了类型的范围。注意这里的属性都是通过宏定义的常量值,宏是预处理的一部分,后面就会讲到。下面是一些部分常用的宏:
- SHRT_MIN,SHRT_MAX:short int的最小值和最大值。
- INT_MIN,INT_MAX:int 的最小值和最大值。
- LONG_MIN,LONG_MAX:long int的最小值和最大值。
- LLONG_MIN,LLONG_MAX:long long int的最小值和最大值。
- USHRT_MAX:unsigned short int的最大值。
- UINT_MAX:unsigned int 的最大值。
- ULONG_MAX:unsigned long int的最大值。
- ULLONG_MAX:unsigned long long int的最大值。
4. 浮点数类型
在C语言中,浮点数是用来表示任何带有小数点的数。C语言规定了三种浮点数类型:float(单精度)、double(双精度)、long double(超长双精度),其占用空间和表示范围都不同。
- float类型:单精度浮点数类型,通常为4个字节(32位),表示有效数字约为6-7位
- double类型:双精度浮点数类型,通常为8个字节(64位),表示有效数字约为15-16位
- long double类型:超长双精度浮点类型,通常为16个字节,表示有效数字与double相同
下面是定义三种浮点数类型变量的例子:
float f = 8.8;//定义一个float类型的变量f,且值为8.8
double d = 88.88;//定义一个double类型的变量d,且值为88.88
long double l = 888.888;//定义一个long double类型的变量l,且值为888.888
C 语言也可以使用科学计数法来表示浮点数,使用字母e
来分隔小数部分和指数部分,小数部分如果是0.
d或d.0
的形式,0
可以省略:
double d = 888.888e+3;//加号可以省略
0.8E8 //等同于.8E8
8.0E8 //等同于8.E8
注意:浮点数的存储方式与整数型不同,比如说float类型,共有32位,采用“8+24”的方式,即8位存放指数的的符号和值,24位存放小数的符号和值。而且由于精度的原因,浮点类型能表示的数值只是一个无限接近的近似值,会存在很小的误差。
C语言中,浮点数被默认指定为double类型,而且浮点数类型也可以加上后缀指定其他浮点数类型;如果需要转为float类型,则在数值后面加上后缀F或者f
float f = 3.14f;//转为float类型
5. 字符类型
C语言中使用char关键字来存储单个字符,但是在计算机中存储需要将字符转换成对应的数字编码,一般是ASCII编码。char类型的变量可以用来表示字符,也可以用来表示字符对应的ASCII码值,两种写法都正确。
C语言中,char类型使用1个字节(8位)存储,因此表示的范围就是-128到127或0-255之间,C语言会把字符当做整数来处理,所以说字符就是经过转换后大小为1个字节的整数,每个字符都对应一个整数。
下面是定义一个字符类型的变量,C语言规定,字符常量值需要用单引号”括起来:
char c = 'A';//定义一个字符类型变量c,值为A
也可以直接写表示字符对应的ASCII码值,具体字符查看ASCII码表,A对应的ASCII值为65:
char c =65;//定义一个字符类型变量c,编码为65
char c = 'A';//等同于上面的语句
char类型可以表示一些转义字符和控制字符,转义字符就是转换字符的意思,主要用于一些控制或者的字符,在字符值前加反斜杠\就可以实现转义,下面是常用的转义字符:
char c = '\'';//表示单引号字符
char c = '\n';//表示换行符
char c = '\t';//表示制表符
char c = '\r';//表示回车符
char c = '\f';//表示换页符
char c = '\b';//表示退格符
char c = '\0';//表示null字符
char x = '\66'; //使用八进制表示一个字符
char x = '\x66'; //表示十六进制表示一个字符
6. 布尔类型
C89的版本里是没有布尔类型的,而是使用整数来表示真假,0就是假,所有非零值就是真:
int a = 0;//表示假
int a = 1;//表示真,所有非零值
C99的版本里增加了布尔类型,使用_Bool来定义,其实本质上还是用整数表示:
_Bool flag;
flag = 0;//表示假
flag = 1;//表示真
还有一种方式就是引入标准库文件stdbool.h,使用关键字bool来定义布尔值,true就表示真,就是1,false就表示假,就是0,默认为false,也就是说C99版本将布尔类型写入了标准。
#include <stdbool.h>
bool flag = false;//表示为假,即为0
bool flag = true;//表示为真,即为1
7. void类型
C语言中,void关键字表示为“无类型‘’,也就是没有值的数据类型,void通常用于函数的返回值类型和函数参数类型,在指针的应用也比较多,void指针可以指向任何数据类型的数据。
void用于函数返回值类型:当函数的返回值类型定义为void时,则表示函数没有返回值,也就是没有return:
void test(int a){
...//返回值类型为void,不需要返回,不需要写return
}
void用于函数参数类型时,则表示该函数不接受任何参数:
int test(void){//不需要任何参数
...
return 0;
}
注意:不能定义void类型的变量,编译时会报错。
8. sizeof运算符
C语言中规定,sizeof运算符可以获取数据类型的大小,以字节为单位返回,sizeof接受一个参数,可以是数据类型名、变量名、字面量值,返回值是无符号整数,但没有规定具体的类型,而是由系统自行决定,这样就影响了C程序的可移植性。
因此,C语言又提供了一种类型size_t,用来统一表示sizeof运算符的返回值,引入stdio.h库文件就可以使用,C语言还规定了size_t的范围,引入SIZE_MAX常量可以表示size_t的范围为0到SIZE_MAX。
C语言的printf()函数中使用%zd或%zu格式可以输出size_t的值。
int a = sizeof(int);//参数为数据类型,返回2或4、8
int a;
sizeof(a);// 参数为变量名,返回2或4、8
sizeof(8.8);//参数为数值,返回8
printf("%zd\n", sizeof(int));//输出size_t
9. 类型转换
9.1 类型自动转换
数据类型的自动转换,也称为隐式转换,是编译器自动将某个值的类型转换为另外一种类型。
当两个不同类型的数据值进行运算时,C编译器会自动转换为同一种类型进行运算。浮点数值赋值给整数类型时,C编译器会全部舍弃掉小数部分:
int a = 3.14;//C编译器将3.14转换为int类型,舍弃小数部分,所以a的值是3
整数赋值给浮点数类型时,会自动转换为浮点数
float f = 3 * 4;//已经自动转为float类型,所以f的值为12.0
大类型转为小类型时,类型会降级,编译器会自动舍去多余的二进制位,丢失数据
int a = 256;
char c = a;//舍弃多余的数据部分
小类型转为大类型时,会发生类型提升,比如short int类型的值赋值给int类型,返回类型为int
short int a = 10;
int i = a;//提升为int类型
9.2 类型运算
不同数据类型的值进行运算时,需要转换为同一种类型才能运算。
一般来说,整型与浮点类型进行运算时,整数类型会先转换为浮点类型,然后才能进行运算,下面的整数值3会先转换为3.0,然后再与1.4相加得到值4.4
3 + 1.4;//4.4
不同的整数类型之间进行运算时,会发生类型提升操作,short int转int,int转long int,long int转long long int
short int a = 1;
int b = 2;
int c = a + b;//a转为int类型
不同的浮点数类型之间进行运算时,也会发生类型提升操作,float转double,double转long double
float f = 3.14;
double d = 6.28;
double x = f + d;//f转为double类型
9.3 强制转换
数据类型的自动转换容易发生数据丢失,因此C语言提供了强制转换,给指定的数据类型加上小括号( )就可以转换为想要转换的类型。
(unsigned int)a;//转换为无符号整数型
int a = 10;
float f = (float)a; // 强制将int类型的a转换为float类型
10. 小结
- C语言的基本数据类型分为整数型、浮点数型、字符型;
- 符号说明符signed和unsigned加上三种基本数据类型就构成了常用的数据类型
- int类型又分为了int、short int、long int、long long int四种类型
- C语言规定,整数和浮点数类型都可以加上不同的后缀来制定数据类型
- C语言中的字符类型定义的值是和ASCII编码相对应的,在执行时需要转换成编码
- C99版本中增加了_Bool宏和bool关键字来支持布尔类型,true为真,false为假
- void类型表示“无类型”,通常用于函数的返回值和函数参数的指定
- sizeof运算符用于计算数据类型大小的计算,size_t用于表示统一返回值类型
- 数据类型的转换分为自动转换和强制转换,自动转换建议小类型转大类型,强制转换需要将类型加上()