目录
数据的类型及类型的基本归类
数据类型及所占存储空间的大小
内置类型 | 单位 | 32位 | 64位 | 备注 |
char | 字节 | 1 | 1 | |
short | 字节 | 2 | 2 | |
int | 字节 | 4 | 4 | |
long | 字节 | 4 | 8 | |
long long | 字节 | 8 | 8 | C99类型 |
float | 字节 | 4 | 4 | |
double | 字节 | 8 | 8 |
类型的意义
1、决定了开辟空间的范围
每个类型所占据字节的大小;
注意点: C语言规定,sizeof(long)>=sizeof(int);
2、决定了如何看待内存空间的视角
给a赋一个整型值,内存空间中存储的是整型的数据,以整型和浮点型读取数据,会得到不同的结果。
int main()
{
int a = 20;
printf("%d\n", a);//结果为20
printf("%f\n", a);//结果为0.000000
system("pause");
return 0;
}
类型的基本归类
整型家族
char | 具体类型由编译器决定 |
signed char | 有符号 |
unsigned char | 无符号 |
short | 默认有符号 |
signed short | 有符号 |
unsigned short | 无符号 |
int | 默认有符号 |
signed int | 有符号 |
unsigned int | 无符号 |
long | 默认有符号 |
signed long | 有符号 |
unsigned long | 无符号 |
long long | 默认有符号 |
signed long long | 有符号 |
unsigned long long | 无符号 |
注意:C语言标准并未定义char类型默认是signed或者unsigned,具体是由编译器指定
有符号与无符号的作用:
signed与unsigned的意义
C语言中有正数与负数,为了方便使用,C语言规定了有符号类型与无符号类型,它们的区别在于最高位,有符号类型最高位是符号位,0代表正数,1代表负数,无符号位最高位不是符号位,是数值位无论0还是1代表的都是数值
浮点数家族
float | 单精度浮点型 | 精度低,存储数值范围小 |
double | 双精度浮点型 | 精度高,存储数值范围大 |
构造类型
数组类型 | type [num] |
结构体类型 | struct |
枚举类型 | enum |
联合类型 | union |
指针类型
普通指针类型 | int *,char *,float *等等 |
空指针类型 | void * |
空类型
void表示空类型(无类型)
通常应用于函数的返回类型,函数的参数,指针类型。
下面的代码中,第一个void表示test函数不需要返回,第二个函数(void)表示整个函数不需要传递参数,如果传参会有警告
void test(void)
{
printf("hehe\n");
}
int main()
{
test();
return 0;
}
整型在内存中的存储
数值的进制
进制 | 范围 |
二进制 | 0,1 |
八进制 | 0~7 |
十进制 | 0~9 |
十六进制 | 0~9,a~f |
注意:实际在内存中,内存都是以二进制的形式保存,但是编译器以十六进制的形式表现
整型值为10
二进制 0b00000000 00000000 00000000 00001010
十六进制 0x00 00 00 0a
二进制的不同表现形式
原码,反码,补码
注意:三种表示方法,均有符号位和数值位两部分,符号位用0表示正,用1表示负;正数的原码、反码、补码都相同;负数的原码、反码、补码是按照计算取得;整型数据存放在内存中是以补码的形式存放;
为什么用补码
原因1:CPU中只有加法器,没有减法器,使用补码能够将减法做加法处理(原码无法进行负数的加法运算),此外补码与原码互换,其运算过程是相同的,不需要额外的硬件电路(原码取反加1得到补码,补码取反加1得到原码;
注意:1000 0000(直接赋值-128),10000000 00000000 00000000 00000000(直接赋值-2,147,483,648))
以整数20为例:
原码:00000000 00000000 00000000 00010100
反码:00000000 00000000 00000000 00010100
补码:00000000 00000000 00000000 00010100
以整数-20为例
原码:10000000 00000000 00000000 00010100
反码:11111111 11111111 11111111 11101011(原码除符号位取反)
补码:11111111 11111111 11111111 11101100(反码+1)
为什么二进制中要存放补码
以1-1为例
1-1=1+(-1)
原码运算(错误)
00000000 00000000 00000000 00000001 (1的二进制)
10000000 00000000 00000000 00000001 (-1的二进制原码)
结果
10000000 00000000 00000000 00000010 (-2)
补码运算
00000000 00000000 00000000 00000001 (1的二进制)
11111111 11111111 11111111 11111111 (-1的补码)
结果
1 00000000 00000000 00000000 00000000
因为是整型,最多只能有32位,所以最高位被丢弃,结果为0
原因2
使用补码能将符号位和数值位统一处理(运算时可以同时考虑数值位和符号位)
大小端字节序
硬件决定了大小端的存储方式
以0x11 22 33 44为例
大端字节序存储:数字的高位存储在低地址中,低位存储在高地址中是大端存储
小端字节序存储:数字的低位存储在低地址中,高位存储在高地址中是小端存储
如何区分电脑是大端存储还是小端
注意:判断大小端一定需要指针,char指针取地址时,取得的是int类型的首地址
int check_sys()
{
int num = 1;
char *pc = #
return *pc;
}
int main()
{
if (check_sys())
{
printf("小端\n");
}
else
{
printf("大端\n");
}
system("pause");
return 0;
}
练习
输出什么
int main()
{
char a = -1;
signed char b = -1;
unsigned char c = -1;
printf("a=%d\nb=%d\nc=%d\n", a, b, c);
system("pause");
return 0;
}
解题思路
-1是整型
二进制补码
11111111 11111111 11111111 11111111
存入char中发生截断,只取最后八位
11111111
char与 signed char 是有符号类型,提升时以符号位为准
11111111 11111111 11111111 11111111
%d是有符号打印
所以打印时结果为-1
无符号类型提升
11111111前全加0
00000000 00000000 00000000 11111111
打印结果为255
题目2
int main()
{
char a = -128;
printf("%u\n", a);
system("pause");
return 0;
}
解题思路
- 128的整型是1000 0000(注意这个数不是计算的而是规定的,有符号位见到就是-128)
-128补码是
原 10000000 00000000 00000000 10000000
反 11111111 11111111 11111111 01111111
补 11111111 11111111 11111111 10000000
存入时发生截断
10000000
打印时进行提升,因为是有符号位
11111111 11111111 11111111 10000000
%u是无符号类型打印,不用转为补码,打印结果是
4294967168
题目3
int main()
{
char a = 128;
printf("%u\n", a);
system("pause");
return 0;
}
解题思路与上面相同
128的补码
00000000 00000000 00000000 10000000
存入时截断
10000000
因为时有符号位,提升时
11111111 11111111 11111111 10000000
无符号打印
4294967168
int main()
{
int i = -20;
unsigned int j = 10;
printf("%d\n", i + j);
system("pause");
return 0;
}
解题思路
-20补码
原:10000000 00000000 00000000 00010100
反:11111111 11111111 11111111 11101011
补:11111111 11111111 11111111 11101100
10补码
补:00000000 00000000 00000000 00001010
相加
11111111 11111111 11111111 11101100
00000000 00000000 00000000 00001010
11111111 11111111 11111111 11110110
有符号打印(读取数据时需要转换位原码)
10000000 00000000 00000000 00001001(取反)
10000000 00000000 00000000 00001010(加1)结果为-10