笔试材料收集(一)——程序员面试宝典(三)第五章
1.如果将a、b的值进行交换,并且不适用任何中间变量?
a = a ^ b;
b = a ^ b;
a = a ^ b;
这三行代码也算是经典吧,对我等菜鸟程序员而言。因为本人生平很少用到这个异或操作符,或者说位操作符都很少用到,只是听说了而已。第一行,a = a^b,a 的值改变了,但是记录了a^b的结果,而且可以说异或的结果是可逆的。正如负负得正一样,a^b^b = a; (a^b)^a = b。
2.下面代码的作用
int f(int x, int y)
{
return (x&y) + ((x^y)>>1);
}
x&y的结果,是将他们当中相同的位,都保留了下来;而x^y的结果,是将他们当中不相同的位,都保留了下来。而相同的位和不相同的位就分别构成了x 和 y。显然相同的位加上不同的位等于 x + y。 2 * (x&y) + (x^y) = x + y。乘以2是因为相同的位,x和y各有一份。
3.用一个表达式,判断一个数X是否是2的N次方(2,4,6,8,...),不可用循环语句。
显然,2,4,6,8,等等数转换成二进制是10、100、1000、10000.。。如果 X 减 1 后与 X 做与运算,答案若是0,则X是2的N次方。
!(X&(X-1))
4.下面这段程序的输出结果。
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <conio.h>
using namespace std;
void main()
{
float a = 1.0f;
cout << (int)a << endl;
cout << &a << endl;
cout << (int&)a << endl;
cout << boolalpha << ((int)a == (int&)a) << endl;
float b = 0.0f;
cout << (int)b << endl;
cout << &b << endl;
cout << (int&)b << endl;
cout << boolalpha << ((int)b == (int&)b) << endl;
cin >> b;
}
结果:
问题就出在 (int&)a 和 (int&)b到底做了些什么,(int&)是对 int 的引用,因此是个地址。(我在X64下运行的,所以地址也是64位的。)既然是地址,他把什么当成了地址呢,就是 a 和 b 的值,他把 a 和 b 所存储的值强制转换成引用。
5.What will be the output of the following C code?
#include <stdio.h>
void main()
{
int b = 3;
int arr[] = {6, 7, 8, 9, 10};
int *ptr = arr;
*(ptr ++) += 123;
printf("%d,%d\n", *ptr, *(++ptr));
}
这是一段非常普通的代码,然而,这里有个陷阱,那就是printf这个函数,它是从右向左开始的。
ptr最初是指向arr的第一个元素,在*(ptr ++) += 123之后,它指向了第二个元素。而在printf当中,从右向左,它又自增了一次,指向了arr的第三个元素。所以,两次输出都为第三个元素,8。
6.以下代码的输出结果。
#include <iostream>
using namespace std;
int func(int x)
{
int count = 0;
while(x)
{
count ++;
x = x&(x-1);
}
return count;
}
int main()
{
cout << func(9999) << endl;
return 0;
}
这段代码是做什么用的呢,关键就在 x = x&(x-1),它会将 x 在二进制代码中的一个值为 1 的位置换位 0。且每次只是转换以为,所以输出就是 x 在二进制形式中1的个数。
7.下面这段代码运行结果的
#include <iostream>
using namespace std;
int main()
{
int a,x;
for(a = 0, x = 0; a <= 1 && !x++; a ++)
{
a ++;
}
cout << a << x << endl;
for(a = 0, x = 0; a <=1 && !x ++;)
{
a ++;
}
cout << a << x << endl;
}
结果:
21
12