include//int cheak_sys(void) //{ // int a = 1; // char* p=(char *)&a; // return *p; //} //int main() //{ // int ret = cheak_sys(); // if (ret == 1) // printf("小端"); // else // printf("大端"); // return 0; //}
上次说到数据存储模式分大端输入和小端输入,这个代码就是用来测你的计算机是哪个端输入模式
思想是自定义一个检查函数,函数里面定义一个整型数字1,他有4个字节也就是32个二进制,补码等于源码是31个0与一个1,我们把它在内存中的地址取出来,强制类型转化
为(char*)指针,也就是把内存中低地址的一个字节八个二进制的地址取出来,对它进行解引用,如果是小端输入的话得到的值为1,就是小端模式,如果是0就是大端模式。
大端小端存储模式前面已经提过。
int main() //{ // char a =-1; // signed char b = -1; // unsigned char c = -1; // printf("a=%d,b=%d,c=%d\n", a, b, c); // printf("a=%u,b=%u,c=%u\n", a, b, c); // return 0; //}
请问输出的应该是什么呢?
a=-1,b=-1,c=255
a=4294967295,b=4294967295,c=255
a是有符号字符型的数字,以%d形式就是有符号的十进制整型输出,首先整型提升,移动补码前面补符号位,补1结果还是-1的补码在转换为源码输出肯定是-1;
以%u形式就是无符号的十进制整型输出,首先整型提升是32个1,以%u输出默认为无符号数,补码等于源码就是2的32次方-1
b同理a所以结果一样
c定义位无符号的字符型是-1;先进行整型提升11111111前面补24个0,在以%d形式输出,源码就是补码就是2的8次方-1同理%也是一样
//int main() //{ // int i = -20; // unsigned int j = 10; // printf("%d", i + j); // //按补码进行计算,最后转化为有符号数 // return 0; //}
-20的源码是 10000000 00000000 00000000 00010100 10的源码是 00000000 00000000 00000000 00001010 补码等于源码
-20的反码是 11111111 11111111 11111111 11101011 -20的补码是 11111111 11111111 11111111 11101100
加起来结果是 11111111 11111111 11111111 11110110
得到的补码减111111111 11111111 11111111 11110101 取反为 10000000 00000000 00000000 00001010这个为-10
int main() //{ // unsigned int i; // for (i = 9; i >= 0; i--) // { // printf("haha\n"); // } // return 0; //}
这个的结果是什么呢?结果是一直死循环打印haha因为unsigned int 型范围是不可能小于零for循环结束不了
nt main() //{ // unsigned char i = 0;//i就不可能大于255 // for (i = 0; i <= 255; i++) // { // printf("haha\n"); // } // return 0; //}
这个同理上个unsigned char范围是0-255它跳不出for循环,也是死循环打印
int main() //{ // char a[1000]; // int i; // for (i = 0; i <= 1000; i++) // { // a[i] =-1-i; // //-1,-2,-3.......-128,127(-128-1),126,....1,0,-1 0的asiia码'\0'128+127 // } // printf("%d", strlen(a)); // return 0; //}
首先定义了一个字符型数组,里面有1000个元素,给设了一个循环给数组初始化,下标是0的第一个元素是-1,依次是-2,-3,-128到了-128char的范围就是-128-127在减少一个数为127直到减到0,因为strlen是求'\0'前面元素的个数,0对应的正好是'\0',所以字符长度为128+127+255结果就是255
int main() //{ // int n = 9; // float* p = (float*)&n; // printf("n=%d\n", n); // printf("*p=%f\n", *p); // *p = 9.0; // //9.0 // //1001.0 // //(-1)^S+M*2^E // //(-1)^0+1.001*2^3 // printf("n=%d\n", n); // printf("*p=%f\n", *p); // return 0; //}
结果是什么呢?
n=9 *p=0.000000 n=1091567616 *p=9.000000
首先分析它是以整型9给存进去,在以%d形式拿出来打印打印的还是9
把n的地址强行转换为浮点型指针给了指针p,9在内存中补码为 00000000 00000000 00000000 00001001转换为浮点型认为它是一个浮点型的数字,以%f取出来的话,
最高位S为0表示正数,后8为为E都是0,有效数字M不在加上第一位的1,还原为0.xxxxxx的小数,E为-126默认是无限接近0的数字
就是(-1)^0*0.0000000 00000000 00001001*2^(-126)打印的是0.000000
然后给p指向的n赋值9.0 9.0写成(-1)^0*1.001*2^3
S为0 E为130为 10000010 M为00100000000000000000000 所以最后为 0 10000010 00100000000000000000000以%d打印就是
以浮点型%f在拿出来还是9.00000000
这个题思想就是整型和浮点型在内存中的存放是不同的,整型形式存储以浮点型打印,以及以浮点型存储,整型拿出结果肯定不一样啊
整型和浮点型在内存中存储方式不一样。整型在内存中是以二进制补码存储的
规定,任意一个浮点数v都可以写成(-1)^S*M*2^E
(-1)^S表示符号位,当s=0时,v为正数,当s=1时,v为负数
M表示有效数字,大于等于1,小于2(M把1.xxxx改为0.xxxx只存小数位,默认有1,使得精度加1)
2^E表示指数位(E在内存中假如是4个字节加127,8个字节加1023)
float存储32个bit位 最高位S 后8位 E 最后23位 M
float存储64个bit位 最高位 S 后11位 E最后52位 M
浮点型数字从内存往出取,
M前面默认加1写成1.xxxxxx形式得到真实值
E假如不全为0或者1,根据多少字节减去127或者1023得到真实值
假如E全为0,有效数字M不在加上第一位的1,还原为0.xxxxxx的小数,E为-126默认是无限接近0的数字
E全为1,表示八个比特位都为11,E的真实值为128表示无穷大的数字。
////int main(void) ////{ //// float a = 1.0;//(-1)^0+0*2^0 //// float b = 9.0; //// float d = 5.5;//(-1)^0+1.011*2^2 //// double c = 1.0;//(-1)^0+0*2^0 //// return 0; ////}
里面把S,M,E拿出来不就知道在内存中存储了,注意M表示有效数字,大于等于1,小于2(M把1.xxxx改为0.xxxx只存小数位,默认有1,使得精度加1)取的时候得加1(E全为0,1除外),E根据多少字节加127还是1023往出取。