大小端的定义以及判断
拿一个整形在内存中的存储来举例,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
若有错误欢迎大家的指正于补充,都看到这里了点个赞吧