一.数据类型分类
数据在内存中,主要以两种形式存储
1.整形家族
- char: signed char,unsigned char 因为字符存储的是ASCII码值,所以也归于整形
- short:signed short,unsigned short
- int:signed int,unsigned int
- long:signed long,unsigned long
2.浮点型家族
- float
- double
其他还有三种类型
3.构造类型
- 数组类型
- 结构体类型
- 枚举类型
- 联合类型
4.指针类型
int*,char*,float*,void*
5.空类型
void
通常用于:函数的返回类型void func(),函数的参数void func(void),指针类型(void*p)
二.整形在内存中的存储
整形可以变为原码,反码,补码存储在内存中
存储可以用"大端存储"或者"小端存储"这两种方式
1.原码,反码,补码
这三种就是一个整形用二进制表示的方法
这三种方法都分有“符号位”和”数值位“两部分,正数的符号位是‘1’,负数的符号位是‘0’
- 正数
原码,补码,反码都相同
- 负数
原码:即整形二进制表达方式
反码:原码符号位(0)不变,其他数值位按位取反
补码:反码+1
最终,在内存中存放的是补码
2.大小端
数据的高低位:
举一个例子,11的二进制表示为
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 1 |
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
变成二进制,一共32个比特位0—31
存储的四位有效数据:1011
即1*2^0 + 1*2^1 + 0*2^3 + 1*2^4
1011这四个数,就代表数据的低位,详细见表格
不难发现数据的高位在前,低位在后
内存的高低地址:
00 | 00 | 00 | 00 |
低 | 高 |
内存低地址在前,高地址在后
现在我们已经知道了数据的高低位和内存的高低位判断,下面就让我们来看大小端这两种存储方式的不同
大端存储:数据的低位保存在内存的高地址中,数据的高位保存在内存的低地址中
小端存储:数据的低位保存在内存的低地址中,数据的高位保存在内存的高地质中
大多数机器存储方式为,小端存储
3.关于整形存储的练习题
在做题前来看看singed和unsigned的区别
有符号,就是大家常见的整形类型,也分符号位和数值位
无符号,这是没有符号位,只有数值位
一般char,short,int,long都表示有符号,默认前面加sigend
unsigned char/short/int/long表示无符号
代码一:
#include <stdio.h>
int main()
{
char a= -1;
signed char b=-1;
unsigned char c=-1;
printf("a=%d,b=%d,c=%d",a,b,c);
return 0;
}
有关a
- 1.算出a=-1的二进制:
原码:1000 0000 0000 0000 0000 0000 0000 0000 0001
反码:1111 1111 1111 1111 1111 1111 1111 1111 1110
补码:1111 1111 1111 1111 1111 1111 1111 1111 1111
- 2.char内存为一个字节,8个比特位,所以发生截断,将32截取后8位留下,其他丢弃
截断补码:1111 1111
- 3.打印为%d,需要整形提升,提高到32位。有符号补1,无符号补0。有符号。
整形提升补码:1111 1111 1111 1111 1111 1111 1111 1111
- 4.最后别忘了恢复原码:补码-1,取反
打印的原码:1000 0000 0000 0000 0000 0000 0000 0001 //符号位不变
- 5.变成十进制
打印数字:a=-1
有关b
char与signed一般相同,所以同上
打印数字:a=-1
有关c
- 1.算出a=-1的二进制:
原码:1000 0000 0000 0000 0000 0000 0000 0000 0001
反码:1111 1111 1111 1111 1111 1111 1111 1111 1110
补码:1111 1111 1111 1111 1111 1111 1111 1111 1111
- 2.char内存为一个字节,8个比特位,所以发生截断,将32截取后8位留下,其他丢弃
截断补码:1111 1111
- 3.打印为%d,需要整形提升,提高到32位。有符号补1,无符号补0。无符号。
整形提升补码:0000 0000 0000 0000 0000 0000 1111 1111 //高位为0,正数,原码即补码
打印的原码:0000 0000 0000 0000 0000 0000 1111 1111
- 4变成十进制
打印数字:c=255
看结果
代码二:
#include <stdio.h>
int main()
{
char a = -128;
printf("%u\n",a);
return 0;
}
解释: %u指以十进制形式打印无符号整形
区别一下%d:指以十进制形式打印有符号整形
解题
- 1.a=-128的二进制:
原码:1000 0000 0000 0000 0000 0000 0000 1000 0000
反码:1111 1111 1111 1111 1111 1111 1111 0111 1111
补码:1111 1111 1111 1111 1111 1111 1111 1000 0000
- 2.char内存为一个字节,8个比特位,所以发生截断,将32截取后8位留下,其他丢弃
截断补码: 1000 0000
- 3.打印为%u,需要整形提升,提高到32位。有符号补1,无符号补0。有符号。
整形提升补码/原码:1111 1111 1111 1111 1111 1111 1000 0000
- 4.
- 5.变成十进制
打印数字:a=4294967168
看看结果
代码三
#include <stdio.h>
int main()
{
char a = 128;
printf("%u\n",a);
return 0;
}
128在发生截断后,高位也被丢弃,正数负数没区别了,和上题一样的结果
代码四
int i= -20;
unsigned int j = 10;
printf("%d\n", i+j);
- 1.i=-20的二进制:
原码:1000 0000 0000 0000 0000 0000 0000 0001 0100
反码:1111 1111 1111 1111 1111 1111 1111 1110 1011
补码:1111 1111 1111 1111 1111 1111 1111 1110 1100
- 2.j=10的二进制:
原码/反码/补码:0000 0000 0000 0000 0000 0000 0000 0000 1010
- 3.相加,
补码:i+j=1111 1111 1111 1111 1111 1111 1111 0110
原码:i+j=1000 0000 0000 0000 0000 0000 0000 1010
- 4.打印十进制
打印数字:a=-10
代码五
unsigned int i;
for(i = 9; i >= 0; i--)
{
printf("%u\n",i);
}
对于这个循环,可以发现,i是无符号数,没办法降到0以下,-1的无符号数这样写:
1000 0000 0000 0000 0000 0000 0000 0001最前面的1不是符号位,是数值位,这时i就是很大的数
从很大的数开始递减
是一个死循环
代码六
int main()
{
char a[1000];
int i;
for(i=0; i<1000; i++)
{
a[i] = -1-i;
}
printf("%d",strlen(a));
return 0;
}
char它被截断后只剩8个比特位,它没办法做到32个比特位那样广阔的选择范围,最后它的数值在-128——127之内,这是说的char的情况,strlen是数\0前面的字符数,最大只能到达255,所以打印的255
代码七
#include <stdio.h>
unsigned char i = 0;
int main()
{
for(i = 0;i<=255;i++)
{
printf("hello world\n");
}
return 0;
}
是个死循环,因为i是char类型,最大只能达到255