目录
一、整数类型
类型 | 存储大小 | 值范围 |
---|---|---|
char | 1字节(8bit) | -128~127 |
int | 2字节或4字节 | -2^15~2^15-1或-2^31~2^31-1 |
short | 2字节 | -2^15~2^15-1 |
long | 4字节 | -2^31~2^31-1 |
1、符号的表示方法
以下内容假设 此处的int占4字节即32bit。
在int类型的32bit位中,左起第一位(即最高位)就是符号位。在int类型的符号位上,0表示正数,1表示负数。在32位操作系统下,后面31位是数值位。
2、数字 0 的表示方法
计算机强行规定了这种情况,数字‘ +0 ’表示为:00000000 00000000 00000000 00000000。而‘ -0 ’这个特殊的数字被定义为-2^31。
因此我们看到的int类型的取值范围为-2^31 ~ 2^31-1,负数部分比正数部分多一个数字。正数部分之所以要减去1,是因为被数字‘ +0 ’占用了,而负数不需要表示‘ -0 ’,因此原本的‘ -0 ’就用来表示-2^31这个数字。
3、符号数的三种表示方法
(1)原码
计算机中一种对数字的二进制定点表示方法。原码表示法在数值前面有一位符号位
正数为0,负数为1(0有两种表示:+0和-0),其余位表示数值的大小。
+1 00000000 00000000 00000000 00000001
-1 10000000 00000000 00000000 00000001
在计算机中不适用原码存储。如下
十进制 | 原码 |
---|---|
1 | 0000 0001 |
-1 | 1000 0001 |
-2 | 1000 0010(加操作) |
总结:计算机在进行加法运算的算法较为简便,减法则是先将被减数转换为负数,在进行加法运算。因此,原码的符号位不能直接参与运算。
(2)反码
正数的反码与其原码相同;负数的反码是对其原码(除符号位),逐位取反。
8位 +1 原码和反码都是 0000 0001
8位 -1 原码是 1000 0001,反码是 1111 1110
十进制 | 原码 | 反码 |
1 | 0000 0001 | 0000 0001 |
2 | 0000 0010 | 0000 0010 |
相加(3) | 0000 0011 | 0000 0011 |
十进制 | 原码 | 反码 |
1 | 0000 0001 | 0000 0001 |
-2 | 1000 0010 | 1111 1101 |
相加 | 1111 1110 | |
结果取反码 | 1000 0001(-1) |
十进制 | 原码 | 反码 |
1 | 0000 0001 | 0000 0001 |
-1 | 1000 0001 | 1111 1110 |
相加 | 1111 1111 | |
结果取反码 | 1000 0000(-0) |
由于 ‘-0’ 的存在使二进制与十进制的互换不再是一一对应
总结:由于-0这个问题的存在,会使得计算机需要增加额外的物理硬件配合运算,所以在计算机发展的早期就已经抛弃了使用反码储存数据。
(3)补码
正数或者+0的补码与其原码相同,负数或者-0的补码则是先得到反码,再将反码+1,得到补码
十进制 | 原码 | 反码 | 补码 |
---|---|---|---|
1 | 0000 0001 | 0000 0001 | 0000 0001 |
-1 | 1000 0001 | 1111 1110 | 1111 1111 |
结果(补码) | 0000 0000 | ||
结果(反码) | 0000 0000 | ||
结果(原码) | 0000 0000 |
*8位2进制补码1000 0000 没有对应的反码和原码,其他的二进制补码与此类似
二、浮点类型
浮点:小数点位置不固定。
类型 | 存储大小 | 值范围 | 精度 |
---|---|---|---|
float | 4字节 | 1.2E-38 到 3.4E+38 | 6位有效位 |
double | 8字节 | 2.3E-308 到 1.7E+308 | 15位有效位 |
long double | 16字节 | 3.4E-4932 到 1.1E+4932 | 19位有效位 |
v = (-1)S * M * 2E
符号位:数的正负,对数值0的符号位解释特殊处理
指数位:2的幂(可能为负数)
有效数字为:尾数位,二进制小数,取值范围为1~2-ε
例子:-9.625
先将9.625转换为二进制 ,即 1001.101
用浮点数表达即为 1.001101*2^3
因为是负数,所以符号段为1。而指数为3,所以指数段为3+127 = 130,即10000010.有效数字省略小数点左侧的1后为001101
即 1 10000010 00110100000000000000000
三、void类型
通常用于以下三种情况
函数返回为空,如void rand(){}
函数参数为空,如rand(void);
指针指向 void,类型为void *的指针代表对象的地址,如void* malloc(size_t size); 返回指向void的指针,可以转换为任何数据。(数据类型的封装)
void指针的意义
c语言规定只有相同类型的指针才可以相互赋值
void*指针作为左值用于“接受”任意类型的指针
void*指针作为右值赋值给其他指针时需要强制类型转换
char *p = (char *)malloc(sizeof(char)*20);malloc返回值为void*
不存在void类型的变量
c语言中没有定义void究竟是几个字节,不同编译器会有不同。而void *为指针,是4字节。
四、枚举类型(enum)
枚举是c语言中的一种基本数据类型,它可以让数据更简洁,代码可读性更强。
1、语法及其默认值
语法格式为:enum 枚举名 {枚举元素1,枚举元素2,……};
例1:
enum DAY
{
MON, TUE, WED, THU, FRI, SAT, SUN
};
第一个枚举成员的默认值为整数类型的 0 ,后续枚举成员的值为前一个成员的值加一。此处MON = 0, TUE = 1, WED = 2, SUN = 6.......
例2:
enum DAY
{
MON = 1, TUE, WED, THU, FRI, SAT, SUN
};
此处MON = 1, TUE = 2, SUN = 7........
例3:
enum DAY
{
MON , TUE, WED=5, THU, FRI, SAT, SUN
};
此处MON = 0, TUE = 1, WED = 6 , THU = 6......
2、枚举变量的定义
1、先定义枚举类型,在定义枚举变量
enum DAY
{
MON, TUE, WED, THU, FRI, SAT, SUN
};
enum DAY day;
2,定义枚举类型的同时定义枚举变量
enum DAY
{
MON, TUE, WED, THU, FRI, SAT, SUN
} day;
3、省略枚举名称,直接定义枚举变量
enum
{
MON, TUE, WED, THU, FRI, SAT, SUN
} day;
实例
#include <stdio.h>
enum DAY
{
MON=1, TUE, WED, THU, FRI, SAT, SUN
} day;
int main()
{
// 遍历枚举元素
for (day = MON; day <= SUN; day++) {
printf("今天是 周%d \n", day);
}
}
运行结果为
今天是 周1
今天是 周2
今天是 周3
今天是 周4
今天是 周5
今天是 周6
今天是 周7
#include <stdio.h>
enum DAY
{
MON=1, TUE, WED, THU, FRI, SAT, SUN
} day;
int main()
{
enum DAY day;
day = WED;
switch(day)
{
case 1:
printf("周一");
break;
case 2:
printf("周二");
break;
case 3:
printf("周三");
break;
case 4:
printf("周四");
break;
case 5:
printf("周五");
break;
case 6:
printf("周六");
break;
case 7:
printf("周天");
break;
default:
printf("error");
}
return 0 ;
}
运行结果:
周三