7道题,讲透整形在内存中存储的原理

目录

前言

百度2015年系统工程师笔试题

练习 2

练习 3

练习 4

练习 5

练习 6

练习 7 


前言

       这一篇练习题继承了上一篇内容的核心,算是上一篇的实战,并且这几道练习题更能加深你对数据在内存中存储的理解。好了,话不多说,先来一张美图直接开始!

 

百度2015年系统工程师笔试题

请简述大端字节序和小端字节序的概念,设计一个小程序来判断当前机器的字节序。(10分)

请大家思考一下。再理解下面的代码:

int  judge()

{

        int i =  1;

        char *pi = (char*)&i;

        return *pi;

}

int main()

{

        int ret = judge();

        if(ret == 1)

        {
               printf("小端模式存储");

        }

        else

        {

                printf("大端模式存储");

        }

        return 0;

}

是不是有思路了,如果你不懂大小端的概念,推荐你看看上一篇:http://t.csdn.cn/CGImA


judge()中的 i  如果是小端模式在内存中的存储形式为0x 01 00 00 00,将&i强制类型转换为char*的指针,取出 01 ,结果就是*pi存储的是 01,转化为十进制与ret判断。如果是大端模式在内存中的存储形式为0x 00 00 00 01, 将&i强制类型转换为char*,取出的就是00了。

上面的judge()函数还可以再简化:

int judge()

{

        int i = 0;

        return  (*(char*)&i);

}

其实还可以用联合体来解决:

int judge()

{

        union

        {

                int i;

                char c;

        }un;

        un.i = 1;

        return un.c;

}

当然还有很多种方法,这里就不一一列举了。

练习 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;

}

思考一下,上面程序输出什么?


上面的输出结果是: a = -1, b = -1, c = 255


-1的补码:1111 1111 1111 1111 1111 1111 1111 1111 

char a 取出的部分(截断) 1111 1111。

然后打印为有符号的整数(%d),需要进行整型提升为:1111 1111 1111 1111 1111 1111 1111 1111 

然后转化为原码打印出 -1。

b同a过程一样(如果编译器默认char == signed,b同a过程一样)。

char c 取出的部分(截断) 1111 1111。

因为c 是无符号类型,进行整型提升前面补0, 为: 0000 0000 0000 0000 0000 0000 1111 1111

看c 提升后的补码可知,c为正数(正数的原,反,补相同)。所以打印为十进制整数为 255(2^7+2^6+2^5+2^4+2^3+2^2+2^1+2^0 = 255)。

练习 3

#include<stdio.h>

int main()

{

        char a = -128;

        char b = 128;

        printf("%u\n",a);

        printf("%u\n",b);

        return 0;

}

思考一下,上面程序输出什么?


两个都为 4294967168


-128的补码为:1111 1111 1111 1111 1111 1111 1000 0000(原码取反加一)

char a 取出的部分: 1000 0000

a进行整型提升(前面补1)为整数:1111 1111 1111 1111 1111 1111 1000 0000

然后以无符号整数打印(%u),编译器会认为 a 没有符号位,是正数,所以直接将a打印成十进制的整数。

128 的原码为:0000 0000 0000 0000 0000 0000 1000 0000(128直接转换为二进制)

char b 取出的部分: 1000 0000

b进行整型提升(前面补1)为整数:1111 1111 1111 1111 1111 1111 1000 0000

然后以无符号整数打印(%u),编译器会认为 b 没有符号位,是正数,所以直接将a打印成十进制的整数。

%u 打印为无符号整数,编译器会认为所打印的数就是正数。

%d 打印为有符号整数,有符号位,需要将补码转换为原码(取反加一)打印出来。

练习 4

#include<stdio.h>

int main()

{

        int i = -20;

        unsigned int j = 10;

        printf("%d\n", i+j);

        return 0;

}       

思考一下,上面程序输出什么?


输出结果为 -10


-20的原码为:1000 0000 0000 0000 0000 0000 0001 0100

-20的补码为:1111 1111  1111  1111  1111  1111  1110  1100(原码取反加一)

10的原码为: 0000 0000 0000 0000 0000 0000 0000 1010

(-20 + 10):1111 1111 1111  1111  1111  1111  1111 0110

接下来打印有符号整数(%d),看符号位为1,所以还得求(-20 + 10)原码:1000 0000 0000 0000 0000 0000 0000 1010,将原码打印成十进制为 -10;

练习 5

unsigned int i;

for( i = 9; i >= 0; i--)

{

        printf("%u\n",i);

}

思考一下,上面程序输出什么?


此程序死循环


 因为 i 为无符号整型,永远大于等于0,i为0的时候,再减一的二进制为全1,编译器会把它当为正数,直接打印。

练习 6

int main()

{

        char a[1000];

        int i = 0;

        for(i = 0; i <  1000; i++)

        {

                a[ i ] = -1 - i;

        }

        printf("%d",strlen(a));

        return 0;

}

思考一下,上面程序输出什么?


输出结果: 255


这里strlen()遇到 "\0" 就会停止读数,而" \0" 就表示为 0,即 0000 0000 0000 0000 0000 0000 0000 0000,而 -1 为 1111 1111 1111 1111 1111 1111 1111 1111,-1不断减 1,需要减255个1才到达 0,所以strlen停止之前,会计算有255个数。

练习 7 

#include <stdio.h>

unsigned char i = 0;

int main()

{

        for(i = 0; i <= 255; i++)

        {

                printf("hello world\n");

        }

        return 0;

}

思考一下,上面程序输出什么?


结果是无限循环


因为 i 是无符号类型的(unsigned),所以它的取值范围为0-255,所以到i增加到255之后,就会变为0,继续加,无限循环。 

好了,感谢大家的观看,到这里就先结束了,拜拜!

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不会背雨霖铃

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值