目录
1.数据类型分类
数据类型可分为两大类:内置类型 和 自定义类型
(本文仅对内置类型做介绍,自定义类型请看后续文章~)
2.内置类型
a.字符型
a.1符号
字符的英文为 character,C语言中用 char 表示字符类型,字符即 单个符号
c
#include <stdio.h>
int main()
{
char a = 'h';
char b = ',';
char c = '8';//'h',',','8'都为字符
return 0;
}
a.2字符与ASCLL码关系
每个字符都对应一个ASCLL码值,ASCLL码表里记录了值和字符的对应情况,字符型变量存储的实际上是字符的ASCLL码值,而不是字符本身
所以,初始化字符型变量(即在定义字符型变量时给变量赋值)时可以直接用ASCLL码来初始化;打印字符时,也可以用ASCLL码值来打印
c
#include <stdio.h>
int main()
{
char a = 'h'; //'h'的ASCLL码值是104(十进制下)
char b = 104;
printf("a = %c,b = %c,c = %c",a,b,104);
return 0;
}
//运行结果为:
//a = h,b = h,c = h
a.3字符型分类
字符类型可分为两种:有符号字符 和 无符号字符
有符号字符: 类型符号为 signed char
无符号字符: 类型符号为 unsigned char注意:,大部分编译器下,char类型的字符默认是有符号字符,即signed被省略了,如vs,也有些编译器里char = unsigned char
有符号与无符号字符的区别在下面讲到有符号整型和无符号整型时再说明
b.整型
b.1符号
整数的英文单词是 integer,C语言中用 int 来表示整型类型
c
#include <stdio.h>
int main()
{
int a = 8;
return 0;
}
b.2整型分类
(下面文字中用中括号 包含的内容表示可以省略)
整型(int)可以分为四种:
短整型: short int ,整型:int,长整型:long int ,更长的整型:long long int
他们的区别可以归纳为:
1.占用的内存大小从小到大(在下面谈sizeof函数时说明),short < int ≤ long ≤ long long
2.能存的数字范围从小到大(在同符号类型中,整型的内存占用越大,可表示的数值范围就越大,因为更多的二进制位可以编码更多不同的数值)
(下面的范围全是有符号整型的范围)
short:-2¹⁵ ~ 2¹⁵-1
int:-2³¹ ~ 2³¹-1
long:4字节 -2³¹ ~ 2³¹-1 或 8字节 -2⁶³ ~ 2⁶³-1
long long:-2⁶³ ~ 2⁶³-1
上面说的这四种整形每种又可以分为 有符号整型 和 无符号整型
有符号整型:可以存 负数,0,正数(与char不同,int = signed int,signed被省略了)
无符号整型:只能存非负数
现在就可以说明char和unsigned char的区别了
前面说过,char类型变量实际上存的是字符对应的ASCLL码值 ,所以,char 和 unsigned char的区别就是:
char存的ASCLL码值可为 负数,0,正数 (-128 ~ 127)
unsigned char存的ASCLL码值只可为 非负数 (0 ~ 255)
(可以注意到,无符号存储的整数最大值大于有符号的,且基本是有符号最大值的两倍,这个原理在后面的原码反码补码文章中会讲到)
c.浮点型
浮点型是用来存储小数的类型(但无法精确存储,原理在后面的存储文章里讲)
c.1浮点型分类
浮点型可分为三类:float(单精度浮点型),double(双精度浮点型),long double(长双精度浮点型)
他们的区别是:
1.占用的内存大小从小到大(在谈sizeof函数时说明),float < double ≤ long double
2.存的数字精度从小到大(三种浮点类型在内存中的二进制尾数位长度依次增加。尾数位用于存储数值的有效数字,位数越多,能保留的有效数字就越多,计算和存储的精度也就越高。)
float:有效数字6-7 位 , double: 有效数字15-16位,long double:有效数字18位以上
3.他们能存储的数字的大小也不同(相对来说这个区别没那么重要)
d.布尔类型
C语言中本来没有布尔类型,是直接用0 表示假, 非0值 表示真
在C99标准中引入了布尔类型,专门表示真假
d.1 符号
布尔类型符号为 _Bool
使用布尔类型要包含头文件<stdbool.h>,而在头文件里,实现了下面的宏定义:
c
#define bool _Bool
#define false 0
#define true 1
所以,在包含了该头文件之后,可以直接用 bool 表示布尔类型,true 表示真 ,false 表示假
c
#include <stdio.h>
#include <stdbool.h>
int main()
{
bool a = true;
bool b = false;
printf("a = %d,b = %d",a,b);
return 0;
}
//运行结果为:
//a = 1,b = 0
3.sizeof操作符
a.数据类型的大小
每一种数据类型都有自己的大小,单位为 字节。使用不同数据类型,可以创建出占用内存大小不同的变量,占用的内存大小不同,存储的数据范围就有差异。
b.sizeof介绍
sizeof是一个操作符,是专门用来计算 操作数 的大小的,它会返回计算的结果,单位为字节
sizeof计算结果的类型为size_t,而size_t表示的是无符号整数
在32位系统上,size_t = unsigned int
64位下,windows是unsigned long long,linux/macos是unsigned long
sizeof的操作数可以为 类型 ,也可以是 变量 和 表达式
(size_t实际上是C标准库中 typedef 定义的别名)【typedef后面会有文章讲到它】
(要使用该类型可以包<stdio.h>这个头文件)
c.sizeof使用
当操作数是 类型时,语法为:
sizeof ( 操作数 )
(括号不能省略)
c
#include <stdio.h>
int main()
{
printf("%zu\n",sizeof(int));//4
return 0;
}
当操作数是 表达式 或 变量时,括号可以省略:
sizeof 操作数
注意:当操作数是表达式时,表达式不会真实计算,sizeof只在编译阶段分析:这个表达式的结果是什么类型?再计算对应类型的大小
请看下面示例,下面代码实现的是对sizeof结果的打印(int类型的大小为4个字节)
c
#include <stdio.h>
int main()
{
int a = 99;
int b = 1;
size_t j = sizeof (a=b+a);
//因为sizeof的高优先级,避免系统按照 j = (sizeof a)=b+a 来理解赋值
//这里给表达式带上括号
printf("%zu\n",sizeof a);//结果为4
printf("%zu\n",sizeof j);//因为表达式结果为int型数据,所以结果为4
printf("a = %d\n",a);
//结果为 a = 99,而不是a = 100
//说明 sizeof(a=b+a) 中a=b+a这个表达式并没有执行,否则a会变成100
return 0;
}
d.借sizeof补充说明内置类型占用内存的大小
上代码
c
#include <stdio.h>
int main()
{
printf("%zu\n",sizeof(_Bool));//结果为 1
printf("%zu\n",sizeof(char));//结果为 1
printf("%zu\n",sizeof(short));//结果为 2
printf("%zu\n",sizeof(int));//结果为 4
printf("%zu\n",sizeof(long));//结果为 4(或者8,由系统决定)
printf("%zu\n",sizeof(long long));//结果为 8
printf("%zu\n",sizeof(float));//结果为 4
printf("%zu\n",sizeof(double));//结果为 8
printf("%zu\n",sizeof(long double));//结果为 8(或者16,同样由系统决定)
return 0;
}
总结:
布尔类型_Bool : 1 字节
字符类型char: 1 字节
整型:
short 2 字节
int 4 字节
long (windows)4 字节(Linux/macOS 64 位)8 字节
long long : 8 字节
浮点型:
float 4 字节
double 8 字节
long double
C标准只规定 long double 精度 ≥ double,没有规定其大小,所以不同编译器可以自由实现。
(windows系统下vs里是8字节, Linux 64 位下gcc里是16字节)
而对于每种类型的有符号(signed)与无符号(unsigned)形式,他们占用内存的大小完全一样,只是解释二进制的方式不同(在后面讲二进制的文章里会讲到),从而使得他们的存储范围不一样
4.数据类型的极限宏常量
每一种数据类型有自己的取值范围,也就是存储的数值的最大值和最小值的区间。
因为在不同系统中数据类型的取值范围可能不同,为了代码的可移植性,也为了方便,
可以使用下面这些宏常量来表示某数据类型的极限值。
SCHAR_MIN , SCHAR_MAX:signed char 的最小值和最大值。
SHRT_MIN , SHRT_MAX:short 的最小值和最大值。
INT_MIN , INT_MAX:int 的最小值和最大值。
LONG_MIN , LONG_MAX:long 的最小值和最大值。
LLONG_MIN , LLONG_MAX:long long 的最小值和最大值。
UCHAR_MAX:unsigned char 的最大值。
USHRT_MAX:unsigned short 的最大值。
UINT_MAX:unsigned int 的最大值。
ULONG_MAX:unsigned long 的最大值。
ULLONG_MAX:unsigned long long 的最大值。
如果要查看当前系统上不同数据类型的极限值,需要包含下面的头文件:
limits.h 文件中说明了整型类型的取值范围。
float.h这个头文件中说明浮点型类型的取值范围。