数据类型的存储

思维导图:

1.整型 

整型的分类:
char(字符型)//因为字符对应的ASSIC码也是整型数字
int(整型)
long (长整型)
long long(长长整型)

2.浮点型

浮点型;
float(单精度浮点型)
double(双精度浮点型)

3.构造类型

构造类型:
数组:int arr[10]
结构体类型:struct
枚举类型:enum
联合类型:union

4.指针类型

指针类型分类:
int *
char*
float*
void*//void*可以转换为任何指针类型

5.空类型

空类型就是void类型,
通常用于表示函数,指针类型

6.三码:原码,反码,补码

6.1补码的意义:

在内存中,计算机存储的是补码。你可能觉得麻烦,但存在即合理。那为什么计算机内存的是补码呢?原来是因为cpu只会算加法。只会算加法就要用补码?我们可以来分析一下:

int main() {
	int a = 1;
	int b = 1;
	int c = a - b;
	printf("%d\n", c);
	return 0;
}

比如上面的代码,cpu计算:a-b=1-1=1+(-1);

原码计算:

 1:    00000000 00000000 00000000 00000001
-1:     10000000 00000000 00000000 00000001
1+(-1): 10000000 00000000 00000000 00000010//-2

计算的结果就是-2.显然不对。

现在我们用补码试一下,看看能不能得到正确的结果:


-1:   10000000 00000000 00000000 00000001//原码
       11111111 11111111 11111111 11111110//反码
       11111111 11111111 11111111 11111111//补码
 1:   00000000 00000000 00000000 00000001//正数的原码,反码,补码相同
1+(-1):00000000 00000000 00000000 00000000//进位,只保留前三十二位。

可以看到在采用了补码的处理方式以后就可以得到正确的结果了。

7.大小端

大端存储:高数据存在低地址(在我们普通人的眼中觉得较为正常的存储方式)

小端存储:低数据存在低地址,高数据存在高地址。

在这里,我闷可以看看vs2019编译器是使用那种类型的存储方式;

 可以看到vs2019使用的是小端存储方式。

但是这是我们自己通过调试的方法查到的,那我们能不能通过一段代码来查找一下呢?

在这里先讲一下思路:比如你将一个1输入进去,1的二进制码是;

00000000 00000000 00000000 00000001,可以看到二进制码里面只有一个1。假如这时,我们再定义一个字符型指针变量来接收内存里的1的二进制码,因为char型变量只接受一个字节。如果是小端存放的话,那字符型变量内就存的是0了。如果是大端存放的话,存的就是1。通过这两个区别我们就可以来设计代码了,代码如下:

int main() {
	int a = 1;
	char *b = (char*)&a;//强制类型转换一下,因为int型与char*不兼容
	if (*b == 1) {
		printf("小端\n");
	}
	else {
		printf("大端\n");
	}
	return 0;
}
	

在这里还可以把代码升级一下:

int check() {//写成函数的形式
	int a = 1;
	return *(char*)&a;
}
int main() {
	int ret = check();
	if (ret == 1)
		printf("小端\n");
	else
		printf("大端\n");
	return 0;
}
	

8.代码练习,加强理解

8.1:

int main() {
	char a = -1;
	signed char b = -1;
	unsigned char c = -1;
	printf("%d %d %d\n", a, b, c);
	return 0;
}

各位看官可以猜一下这段代码的结果是什么?

相信很多人会迷惑,不就是打印-1吗?有什么好猜的?现在来看看结果是否如各位所料:

可以看到结果似乎不是这样子的。

这是为什么呢?

分析:
  整型-1:11111111111111111111111111111111//补码
字符型-1:11111111//只有八位,因为字符型只有一个字节的大小。

 

a:11111111  整型提升:11111111 11111111 11111111 11111111
//在前面补符号位,补够32个比特位
b:11111111  整型提升:11111111 11111111 11111111 11111111
//在前面补符号位,补够32个比特位
c:11111111  整型提升:00000000 00000000 00000000 11111111
//因为c是无符号变量,没有符号位,所以在前面补零

 可以看到,在发生整型提升以后,c就与a,b变量不同了。也就是这个不同,导致了c变量的结果的不同。

8.2:

int main() {
	char a = -128;
	printf("%u\n", a);//打印无符号形式的a
	return 0;
}

各位看官可以来猜一猜这一段代码打印的又是什么呢?

看看答案:

 可以看到打印的竟然不是-128而是一个奇奇怪怪的数字,那这是怎么来的呢?

-128:10000000 00000000 00000000 10000000
     //原码
      11111111 11111111 11111111 01111111
     //反码
      11111111 11111111 11111111 10000000
     //补码
现在用一个字符型接收-128:100000000//发生截断只接收8个比特位

打印时发生整型提升:11111111 11111111 11111111 10000000
          //要打印时就是打印这个,%u这个变量的原码,
反码,补码相同,打印的值就是这个二进制的值

 

这个二进制对应的就是那个奇怪的值。

8.3:

int main() {
	unsigned int i = 0;
	for (i = 9;i >= 0;i--) {
		printf("%u\n", i);
	}
	return 0;
}

 聪明的你在将这个代码输入到聪明的vs编译器以后会发现这个代码是执行不了的:

unsigned int:一直大于0,导致上面的那段代码会无限进行下去。所以会报错。

8.4:

#include<string.h>
int main() {
	char a [1000];
	for (int i = 0;i < 1000;i++) {
		a[i] = -1 - i;
	}
	printf("%d\n", strlen(a));
	return 0;
}

这段代码的答案会是1000吗?

答案是:不会。

为什么呢?

//1.我们都知道,strlen()遇到'\0'时才会停下所以我们只要找到'\0'
在哪里就可以了。
//2.字符型变量里的0就是'\0',那我们找到0就行了。

 找到0:

 因为char型变量的范围是-127~128,所以-1-i,在剪完一圈以后,也就是上面的圈圈逆时针走一圈就找到0了。这一圈的长度就是255。

8.5:

int main() {
	unsigned char  i = 0;
	for (i = 0;i <= 255;i++) {
		printf("Hello wolrd!!!");
	}

	return 0;
}

猜猜会发生什么?

 死循环,没错,就是死循环。因 unsigned char变量的范围是0~255一定不会超过255。

好了,今天的分享就到这里了,如有错误,感谢指正。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值