目录
前言
这一篇练习题继承了上一篇内容的核心,算是上一篇的实战,并且这几道练习题更能加深你对数据在内存中存储的理解。好了,话不多说,先来一张美图直接开始!
百度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,继续加,无限循环。
好了,感谢大家的观看,到这里就先结束了,拜拜!