0、知识点
正整数:原码、反码、补码相同
负整数:原码、反码、补码要进行计算
1、整数在内存中存储的就是补码
通过内存看a的地址 ,把内存调为4列,即看到4个字节, 而这四个字节为什么是这样?
先根据数值写出32二进制- - -原码 1000 0000 0000 0000 0000 0000 1100
原码符号位不变,其他位取反----反码 1111 1111 1111 1111 1111 1111 0011
反码+1-- – -- -补码 1111 1111 1111 1111 1111 1111 0110
补码转换为16进制为 FFFFFFF6(和内存的地址一样)
所以通过十六进制的表示可以看出- - -整数在内存中存储的就是补码
2、减法运算,但其实cpu中只有加法
先换位补码再进行加法运算
1-1
1+(-1)
-1的从原码到补码的转换
10000000000000000000000000000001(-1的原码)
11111111111111111111111111111110(-1的反码)
11111111111111111111111111111111(-1的补码)
00000000000000000000000000000001 (1的原码即补码)
11111111111111111111111111111111 (-1的补码)
100000000000000000000000000000000 (相加之后33位,多出来的高位1被去掉得到下面)
00000000000000000000000000000000
3大端字节序和小端字节序
大端–把数据的低位字节序的内容存放在高地址处,高位字节序的内容存放在低地址
小端–把数据的低位字节序的内容放在低地址,高位字节序的内容存放在高地址
int main()
{
int a=0x11223344;
return 0;
}
- 44为低位字节
- vs2013–小端方式
先把a的地址存储再存放b的地址
int main()
{
int a=0x11223344;
int b=0x01020304;
return 0;
}
判断当前机器的字节序
int 在内存中存储涉及大小端- -可以通过上述例子看第一个字节是01还是00来判断大小端更加方便
看第一个字节是什么-- --通过char* p来拿取
int check_sys()
{
int a = 1;
char* p = (char*)&a;//int*
return *p;//返回1表示小端,返回0表示大端
}
int main()
{
写代码判断当前机器的字节序
int ret = check_sys();
if (ret == 1)
{
printf("小端\n");
}
else
{
printf("大端\n");
}
return 0;
}
4、题
相关知识点
- char 到底是signed char 还是unsigned char ,C语言标准并没有规定,取决于编译器
- 但是默认int 是 signed int ,short 是 signed short
- 需不需要提升- -看它本身的类型和打印类型的相差(或者是两种类型的数比较或者加减乘除的时候,有一种需要提升),如本身为char打印用(有无符号)整型打印,需整型提升
- 整型提升的时候要看本身是有符号还是无符号,有符号提升加1,无符号提升加0
- 整型提升后看得到的数是不是正数,正数–不需要转换为补码,补码即原码,负数–如果不是以无符号来打印则需要转换为补码
打印什么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);
}
解析
#include <stdio.h>
int main()
{
char a = -1;
10000000000000000000000000000001 //-1的原码
11111111111111111111111111111110 //反码
11111111111111111111111111111111 //补码
char是一个字节,8个比特位,取32位后面的8个
11111111
以%d来打印则要按符号位来整形提升得到32位1
11111111111111111111111111111111,
(32位1是补码要再返回到原码为-1的时候打印,和上述原反补的过程反过来)
signed char b = -1;//也是有符号的,整形提升和打印过程和char a一样
11111111
unsigned char c = -1;
11111111
无符号整型提升
00000000000000000000000011111111
整形提升得到的数为正数,则补码为原码
printf("a=%d,b=%d,c=%d", a, b, c);
打印: -1 -1 25
return 0;
}
打印什么2
%u打印无符号数
#include <stdio.h>
int main()
{
char a = -128;
printf("%u\n", a);
return 0;
}
解析
#include <stdio.h>
int main()
{
char a = -128;
-128的原码
//10000000000000000000000010000000
反码
//11111111111111111111111101111111
补码
//11111111111111111111111110000000
char是一个字节,8个比特位,取32位后面的8个
//10000000
以%u(无符号整型)进行打印--需整形提升---因为char是有符号,则提升的时候有符号提升
//11111111111111111111111110000000
以无符号来打印的时候,上面的数看成无符号,补码就是原码,直接打印这个很大的数字
printf("%u\n", a);
return 0;
}
打印什么3
#include <stdio.h>
int main()
{
char a = 128;
printf("%u\n", a);
return 0;
}
解析
#include <stdio.h>
int main()
{
char a = 128;
//00000000000000000000000010000000 - 原返补相同
char是一个字节,8个比特位,取32位后面的8个
//10000000
以%u(无符号)整型进行打印--需整形提升---因为char是有符号,则提升的时候有符号提升
//11111111111111111111111110000000
//以无符号来打印的时候,上面的数看成无符号,补码就是原码,直接打印这个很大的数字
printf("%u\n", a);
return 0;
}
char,有符号的取值范围
以0开头 范围0~127
以1开头 范围-1~-128 (负数要进行原反补的转换)
感觉这个数太大能存储下吗?
char 129
00000000000000000000000010000001
10000001 - 正数-原码-补码
1000000 - 反码
11111111 - 原码
-127
127+1就会变成-128
-128往上走会变成-127…
129也会变为-127- -即127+1+1
圆圈图:
char类型·无符号-无原反补
两数相加输出是什么1
输出-10
int main()
{
int i = -20;
unsigned int j = 10;
printf("%d\n", i+j);
return 0;
}
解析
int main()
{
int i = -20;
原码
//10000000000000000000000000010100
反码
//11111111111111111111111111101011
补码
//11111111111111111111111111101100
unsigned int j = 10;
//00000000000000000000000000001010//正数 原反补 一样
printf("%d\n", i+j);
两数相加得到负数---补码(如果以%u输出就直接输出这个数就可以了,不用补码转换为原码,因为补反一样)
//11111111111111111111111111110110
补码转换为反码
//11111111111111111111111111110101
反码转换得到原码
//10000000000000000000000000001010 -> -10
return 0;
}
两数相加输出是什么2
int main()
{
unsigned char b = 200;
unsigned char b = 100;
unsigned char c = 0;
c = a + b;
printf("%d %d", a + b, c);
return 0;
解析
int main()
{
//unsigned char 0~255
unsigned char a = 200;
//00000000000000000000000011001000(200的原码--正数--即补码)
//11001000
unsigned char b = 100;
//00000000000000000000000001100100(100的原码--正数--即补码)
//01100100
unsigned char c = 0;
//a和b整形提升
//00000000000000000000000011001000
//00000000000000000000000001100100
//00000000000000000000000100101100(a+b的二进制)
c = a + b;
//00101100(因为c是char类型,char是一个字节,8个比特位,取32位后面的8个)
//00000000000000000000000000101100(以%d输出整型提升)
printf("%d %d", a + b, c);
打印: 300 44
return 0;
//}
输出255
int main()
{
char a[1000];
int i;
for (i = 0; i < 1000; i++)
{
a[i] = -1 - i;
}
//-1 -2 -3 ... -127 -128 127 126 125 .. 3 2 1 0 -1 -2 .. -127 -128 127 ...(看着圆圈图写,为什么突然出现127,是因为-129没有,所以按照循环的顺序用下一个127,也可以看成256+(-129))
printf("%d\n", strlen(a));//找到 \0 ,0的前面有128+127 = 255字符
return 0;
}
无符号的char(永远为正) 0-255,死循环
#include <stdio.h>
unsigned char i = 0;
int main()
{
for (i = 0; i <= 255; i++)
{
printf("hello world\n");
}
return 0;
}
int main()
{
unsigned int i;
for (i = 9; i >= 0; i--)
{
printf("%u\n", i);
}
return 0;
}
知识点
int n,n有四个字节
float 解引用·访问4个字节
double解引用·访问8个字节
char解引用·访问1个字节–8个比特位
- -浮点型和整型的存储和取出来的方式不一样,
所以整型n以浮点型打印不会是9.00000
当再次以浮点型视角存储的时候,以整型打印的时候也得不到9
IEEE754
题1
十进制5.5 (小数和小数点后面的数分开来转化,小数为0.5即2^(-1))
二进制101.1--->1.011×2^2-- -- -- --- ->(-1)^ 0 × 1.011 × 2^2
s=0 M=1.011(一般那个小数点前面的1会默认去掉) E=2(无符号)
题2
十进制:0.5
二进制:0.1--->1.0*2^(-1),
此时E为负数,但是E为无符号
所以存入的时候float类型加127,double加1023
- 在IEEE中M存储小数点后面的数float 32个比特位 double 64个byte
浮点型在内存中是怎么样存储的
int main()
{
float f = 5.5f;
return 0;
}
解析
int main()
{
float f = 5.5f;
//101.1
//1.011×2^2
//s=0 M=1.011 E=2
//s=0 M=011 E=2+127
根据上面写出 s=0, E=10000001 M=011 0000 0000 0000 0000 0000
//0 10000001 011 0000 0000 0000 0000 0000
转化成16进制后
//40 b0 00 00
return 0;
}
看内存
- 存入得到32位后想要取出E减去127,M要在小数点后面加回存入的时候去掉的1,E为全0的时候例外
取出可能E全为0或者1,
打印0.00000
#include <stdio.h>
int main()
{
int n = 9;//4byte
float* pFloat = (float*)&n;
printf("n的值为:%d\n", n);
printf("*pFloat的值为:%f\n", *pFloat);//打印0.00000
*pFloat = 9.0;
printf("num的值为:%d\n", n);//打印一个很大的数
printf("*pFloat的值为:%f\n", *pFloat);//打印9.0
return 0;
}
打印浮点数为0.00000
n为9,以浮点型拿出来,打印浮点数的时候就是0.0000
打印一个很大的数
*pFloat = 9.0,把9.0存放进去- -得到的二进制为正数–补码为原码,直接打印 ,打印一个很大的数
float—以%d输出
先写出它的二进制表示,再用科学技术法求出32位二进制
再看它是否正数,补码就是它的本身输出就是这个二进制