有人说学编程其实就是在学内存,如果对内存的理解不够就很容易写出莫名其妙的代码,导致错误的结果,今天我们就来看一下我们常见的一些数据,如:整数和浮点数在内存中是如何存储的,感兴趣的小伙伴快来围观吧~
本篇的练习解析全部都放在了《配套《数据在内存中的存储》》
之前已经在《二进制与原、反、补码》中讲解过整数为什么要有二进制,并且计算机中的整数都是以补码的形式存储的 大家可以自行跳转《二进制与原、反、补码》查看
在详细的讲解什么是大小端字节序之前,我们先来看一个代码调试中容易被忽略的小细节:

很容易就能发现这里的地址由低到高位是44 33 22 11 排序的,然后这里的a由低位(可以理解为二进制的个位)到高位也是44 33 22 11 排序的,我们把这种排序方式称为小端字节序 反之,如果地址由低到高位是11 22 33 44 的话,则称为大端字节序
具体概念为:
为什么会有⼤⼩端模式之分呢?
char 之外,还有16bit的 short 型,32bit的 long 型(要看具体的编译器),另外,对于位数⼤于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度⼤于⼀个字节,那么必然存在着⼀个如何将多个字节安排的问题。因此就导致了⼤端存储模式和⼩端存储模式。short 型 x ,在内存中的地址为 0x0010 , x 的值为 0x1122 ,那么
0x11 为⾼字节, 0x22 为低字节。对于⼤端模式,就将 0x11 放在低地址中,即 0x0010 中,0x22 放在⾼地址中,即 0x0011 中。⼩端模式,刚好相反。我们常⽤的 X86 结构是⼩端模式,⽽KEIL C51 则为⼤端模式。很多的ARM,DSP都为⼩端模式。有些ARM处理器还可以由硬件来选择是⼤端模式还是⼩端模式。很显然,对于这题来说,要想知道字节序,只需要识别一下最小和最大的地址处的字节大小就好了 例如:
int main()
{
int a = 0x11223344;
if (*(char*)&a > *((char*)&a+3))//假设低处地址是44(即小端模式)
{
printf("小端");
}
else
{
printf("大端");
}
return 0;
}在x86环境下,运行结果为:
小端或者换一种方法:
//代码1
#include <stdio.h>
int check_sys()
{
int i = 1;
return (*(char *)&i);
}
int main()
{
int ret = check_sys();
if(ret == 1)
{
printf("⼩端\n");
}
else
{
printf("⼤端\n");
}
return 0;
}
//代码2
int check_sys()
{
union
{
int i;
char c;
}un;
un.i = 1;
return un.c;
}
//代码2为代码1的化简版#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,b=-1,c=255#include <stdio.h>
int main()
{
char a = -128;
printf("%u\n",a);
return 0;
}运行结果:
4294967168#include <stdio.h>
int main()
{
char a = 128;
printf("%u\n",a);
return 0;
}运行结果:
4294967168#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;
}运行结果:
255#include <stdio.h>
unsigned char i = 0;
int main()
{
for(i = 0;i<=255;i++)
{
printf("hello world\n");
}
return 0;
}运行结果:
hello world
hello world
hello world
...
//死循环#include <stdio.h>
int main()
{
unsigned int i;
for(i = 9; i >= 0; i--)
{
printf("%u\n",i);
}
return 0;
}运行结果:
//对于运行结果想必大家也猜到了
9
8
7
6
5
4
3
2
1
0
4294967295
4294967294
//...循环#include <stdio.h>
//X86环境 ⼩端字节序
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;
//%x意思是16进制输出
}运行结果:
4,2000000#include <stdio.h>
int main()
{
int n = 9;
float *pFloat = (float *)&n;
printf("n的值为:%d\n",n);
printf("*pFloat的值为:%f\n",*pFloat);
*pFloat = 9.0;
printf("num的值为:%d\n",n);
printf("*pFloat的值为:%f\n",*pFloat);
return 0;
}运行结果:
n的值为:9
*pFloat的值为:0.000000
num的值为:1091567616
*pFloat的值为:9.000000说明: 根据国际标准IEEE(电⽓和电⼦⼯程协会)754,任意⼀个⼆进制浮点数V可以表⽰成下⾯的形式:

IEEE 754规定:
即:


如图,float类型浮点数在内存中是这样分配的