一道简单有趣的C语言面试题

来源:互联网 发布:蜂窝移动网络走流量吗 编辑:程序博客网 时间:2024/05/22 13:51

昨天收到网友的一个题目,很简单,但是覆盖了不少基础的问题,

很惭愧我计算错了,所以记下来


题目很简单:

unsigned s = 555;

int  i = (s >> 4) & ~(~0 << 3)

cout << i


要求是不通过编程能够求出输出


这里涉及到几个很基本的东西:

1. unsigned s = 555, 我们一般写的时候会加上int 或者其他 类型限制符,但这么写是没有问题的,绝大多数编译器都会默认成unsigned int

2. 移位符号,相信很多人都不记得这两个符号了,至少我不太记得了,只知道是移位,但是不确定是补0还是补1,最后翻了翻书,都是补0

3. 取反符号,按位取反

4. & 运算

6. 进制转换


如果不是计算机专业的,可能对着移位、取反的概念不明白,这是相对二进制而言的运算,在下面的计算过程中讲解


首先,既然涉及到移位和取反运算,我们首先要把数字转换成二进制的,进行进制转换

看到  s = 555

10进制转换的最基本方法很简单,就是除法,每轮的余数作为低位,结果作为下一轮的被除数,每轮的除数等于目标进制

方法一 直接转换成二进制:

简单说来 555/2 = 277 余 1, 277/ 2 = 138 余1, 138 /2 余 0,69 / 2 余 1, 34 /2 余 0, 17/2 余 1, 8 /2 余0, 4/2 余0 ,2/2 余0, 1/2余1

OK,最早除的在最低位,因此 换成二进制是 1000101011

我们的机器假设是32位的,这样就有 0000 0010 0010 1011

但是我更喜欢的是第二种

方法二 10进制转16进制再8421法转2进制:直接转换成16进制,然后再用8421转换成2进制

555/ 16 余11, 34 / 16 余 2, 2/ 16 余 2,因此 16进制数是  0x022B

然后用8421码转换: 0 = 0000, 2 = 0010, B = 1011,因此转换后成为 0000 0010 0010 1011

两种办法都可行,我个人喜欢第二种而已(转换进制不记得导致计算错了,最后赶紧复习了下敲打


OK,数据准备好了,开始运算

S >> 4 = 0000 0000 0010 0010  (无论左移还是右移,都是补0)

~0 = 0xffff = 1111 1111 1111 1111

~0 << 3 = 1111 1111 1111 1000

然后 ~(~0 << 3) = 0000 0000 0000 0111


接着,0x0022和 0x0007进行&运算, 0 & 1 = 0, 0&0 = 0, 1 & 1 = 1, 1 &0 = 0

因此我们按位做运算,得到 0000 0000 0000 0010 = 2


这个结果跟编程输出的结果是一致的

原创粉丝点击