整数在内存中的存储

大小端的定义以及判断

拿一个整形在内存中的存储来举例,int类型占32个bit,4个字节,为了便于观察利用一个特殊的例子0X11223344刚好占4个字节。

在0x11223344中1的位置是高位字节,4低位字节。我们再打开VS中的调试查看它的内存存储会看到

大家有没有想过为什么是44 33 22 11不是11 22 33 44呢,这里涉及到了大小端的问题。

先声明一下大小端的定义,在为大家详细的介绍大小端:

大端存储全名大端字节序存储,低位字节放在高地指处,高位字节放在低地处

小端存储全名大端字节序存储,低位字节放在低地指处,高位字节放在高地处

那么为什么要分出大小端呢,在内存中最小的内存空间是一个字节,char类型只占一个字节,但更多的类型占多个字节由于寄存器宽度⼤于⼀个字节,那么必然存在着⼀个如何将多个字节安排的问题。因此就导致了⼤端存储模式和⼩端存储模式。

源码,反码,补码

一个数字在内存中的储存方式为2进制这是因为电脑是一个电子元件,既然通电就有正电和负电,所以电脑采用2进制来存储。

1.正数的源码,反码,补码都相同

2.如果是负数在内存中存的是补码,我们就需要了解三码间的转化规律

原码———>反码————>补码

a.原码的符号位不变,其他位按位取反得反码到

b.反码加一是补码

c.补码取反加一是原码

习题1:

请简述⼤端字节序和⼩端字节序的概念,设计⼀个⼩程序来判断当前机器的字节序。(10分)百度笔试题

#include <stdio.h>
int main()
{
	int a = 1;
	int b = (*(char*)&a);
	if (b == 1)
		printf("小端存储");
	else
		printf("大端存储");
}

习题2:

#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;
}

char 默认为无符号的char,取值范围为-128~127,所以a和b的值没什么问题就是-1,但unsigned char的取值范围是0~255,所以这里的-1要怎么解决呢?


 

这里我们可以用到一个轮回的思想在元的左边是所有负数,右边是所有正数(这里是char类型)

由图可知在unigned char下的-1位255

习题3:

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

本题计算istrlen(a)就是找a[i]里的0,那么就慢慢向后找就行及从-1到-128再到127到0

习题4:

#include <stdio.h>
int main()
{
char a = 128;
printf("%u\n",a);
return 0;
}

以%u的形式打印的意思是以unsigned int 类型打印,所以要先整形提升

10000000----->11111111111111111111111110000000(补码)

                         10000000000000000000001111111

                         1000000000000000000001000000(原码)

所以结果是一个很大的数字

习题5:

#include <stdio.h>
unsigned char i = 0;
int main()
{
	for (i = 0;i <= 255;i++)//0<i<255
	{
		printf("hello world\n");
	}
	return 0;
}

unsigned char的取值范围是0~255,就说明无法跳出for循环,就会无限打印hellio world

习题6:

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

在vs上运行时会告诉我们For的定义有误会无限执行,虽然有警告但是可以执行,要写错代码也没人能拦得住哈哈哈哈哈

习题7:

#include <stdio.h>
int main()
{
int a[4] = { 1, 2, 3, 4 };
int *ptr1 = (int *)(&a + 1);
int *ptr2 = (int *)((int)a + 1);
printf("%x,%x", ptr1[-1], *ptr2);
return 0;
}

在解决题前要知道这个题在X86,小端存储的情况下运行的

指针ptr1,就是(&a+1)强制转化为int*得到的,所以指向的位置与&a+1的位置相同

ptr[-1]就等价于*(ptr-1),所以打印的结果就是4

指针ptr2就开始上强度了

这里我们要先了解一下数组a在内存中的存放

数组先转化成int 型,然后加1,并取出一个int型的地址

所以向后取出一个int型的地址,及向后找4个字节的地址

最后以16进制打印得到了2000000

若有错误欢迎大家的指正于补充,都看到这里了点个赞吧

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值