【C语言(十二)】
数据在内存中的存储
一、整数在内存中的存储
整数的2进制表示方法有三种,即 原码、反码和补码
正整数的原、反、补码都相同。
负整数的三种表示方法各不相同。
对于整形来说:数据存放内存中其实存放的是补码。
二、大小端字节序和字节序判断
当我们了解了整数在内存中存储后,我们调试看?个细节:
#include <stdio.h>
int main()
{
int a = 0x11223344;
return 0;
}
调试的时候,我们可以看到在a中的 0x11223344 这个数字是按照字节为单位,倒着存储的。这是为什么呢?
2.1、什么是大小端??
上述概念需要记住,方便分辨大小端。?
2.2、为什么会有大小端?
2.3、练习
2.3.1、练习1:
//代码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.3.2、练习2:
#include <stdio.h>
int main()
{
char a= -1;
//1000 0000 0000 0000 0000 0000 0000 0001
//1111 1111 1111 1111 1111 1111 1111 1110
//1111 1111 1111 1111 1111 1111 1111 1111
//存储在a中要发生截断
//11111111 - a
//1111 1111 1111 1111 1111 1111 1111 1111
//1000 0000 0000 0000 0000 0000 0000 0000
//1000 0000 0000 0000 0000 0000 0000 0001
signed char b=-1;
//11111111 - b
unsigned char c=-1;
//11111111 - c
//0000 0000 0000 0000 0000 0000 1111 1111
printf("a=%d,b=%d,c=%d",a,b,c);//-1 -1 255
//%d - 十进制的形式打印有符号的整数
return 0;
}
2.3.3、练习3:?
#include <stdio.h>
int main()
{
char a = -128;
//1000 0000 0000 0000 0000 0000 1000 0000
//1111 1111 1111 1111 1111 1111 0111 1111
//1111 1111 1111 1111 1111 1111 1000 0000
//10000000 - a
//打印时发生整型提升
//1111 1111 1111 1111 1111 1111 1000 0000
printf("%u\n",a);//4,294,967,168
//%u 是十进制的形式打印无符号的整数
return 0;
}
#include <stdio.h>
int main()
{
char a = 128;//128 = 127 + 1 = -128
printf("%u\n",a);
return 0;
}
2.3.4、练习4:?
#include <stdio.h>
int main()
{
char a[1000];
//-128 ~ 127
//-1 -2 -3 ... -128 127 126 125 ... 5 4 3 2 1 0 -1 -2 ... -128 127 126 ... 5 4 3 2 1
//128 + 127 = 255
int i;
for(i=0; i<1000; i++)
{
a[i] = -1-i;
}
printf("%d",strlen(a));//求字符串长度找的是\0,\0的ASCII码值是0,其实找的就是0
//255
return 0;
}
?2.3.5、练习5:
#include <stdio.h>
unsigned char i = 0;
int main()
{
for (i = 0; i <= 255; i++)
{
printf("hello world\n");
}
return 0;
}
#include <stdio.h>
#include <windows.h>
int main()
{
unsigned int i;
for (i = 9; i >= 0; i--)
{
printf("%u\n", i);
Sleep(1000);//睡眠1秒
}
return 0;
}
2.3.6、练习6:?
#include <stdio.h>
int main()//x86环境下
{
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;
}
三、浮点数在内存中的存储
3.1、练习:
#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;
}
①有些浮点数在内存中无法精确保存
②double类型的精度比float更高
③两个浮点数比较大小的时候,直接使用 == 比较可能存在问题!
比如:
5.6 ->?5.59999787897
f == 5.6
解决办法:给一个精度0.000001
if(abs(f?- 5.6) <= 0.000001);//((f - 5.6) >= -0.000001) && ((f - 5.6) <= 0.000001)
3.2、浮点数的存储
要理解这个结果,?定要搞懂浮点数在计算机内部的表示方法。
根据国际标准IEEE(电气和电子工程协会) 754,任意?个?进制浮点数V可以表示成下面的形式: ?
举例来说:
十进制的5.0,写成?进制是 101.0 ,相当于 1.01×2^2 。
那么,按照上面V的格式,可以得出S=0,M=1.01,E=2。
十进制的-5.0,写成?进制是 -101.0 ,相当于 -1.01×2^2 。那么,S=1,M=1.01,E=2。
IEEE 754规定:
对于32位的浮点数,最高的1位存储符号位S,接着的8位存储指数E,剩下的23位存储有效数字M。
对于64位的浮点数,最高的1位存储符号位S,接着的11位存储指数E,剩下的52位存储有效数字M。
????????????????????????????????????????????????????????float类型浮点数内存分配
???????????????????????????????????????????????????????????????????????double类型浮点数内存分配
3.2.1、浮点数存的过程?
IEEE 754 对有效数字M和指数E,还有?些特别规定。?
至于指数E,情况就比较复杂。
3.2.2、浮点数取的过程?
指数E从内存中取出还可以再分成三种情况:?
E不全为0或不全为1
0 01111110 00000000000000000000000?
E全为0?
0 00000000 00100000000000000000000?
E全为1 ?
这时,如果有效数字M全为0,表示±无穷大(正负取决于符号位s)
0 11111111 00010000000000000000000?
3.3、题目解析?
0000 0000 0000 0000 0000 0000 0000 1001
显然,V是?个很小的接近于0的正数,所以用十进制小数表示就是0.000000。?
再看第2环节,浮点数9.0,为什么整数打印是1091567616?
首先,浮点数9.0 等于?进制的1001.0,即换算成科学计数法是:1.001×2^3
0 10000010 001 0000 0000 0000 0000 0000
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!