面试知识点笔记
x=x&(x-1),表示去除x二进制表示的最后一个1位。很容易理解,x-1将最后一个1变成了0,然后与x按位与,新产生的1全变成0
面试题:
#include <stdio.h> main() { int b = 3; int arr[] = {6, 7, 8, 9}; int* ptr = arr; *(ptr++) += 123; printf("%d, %d\n", *ptr, *(++ptr)); }
在程序第7行中,相当于*ptr += 123; ptr++; 因此实际上是将arr第一个数组加了123.
另外,C语言的printf计算参数时是从右到左压栈的,因此第8行先执行++ptr,此时指向的是arr数组的第三个元素。因此输出的是8 8
float a=1.0f; cout << (int&)a; 并不是表示将a强制转化为int地址类型,而是表示将a在计算机中的表示按int类型输出,超过sizeof(int)中的部分自动截掉。
printf("%08x", a); 表示将a按十六进制输出,给8位占位符,不够的左边填充0,右对齐。具体可看文章:http://www.cnblogs.com/growup/archive/2012/01/20/2328077.html
面试题:
#include <iostream> int main(){ unsigned char a = 0xA5; unsigned char b = ~a >> 4 + 1; printf("%d\n", b); system("PAUSE"); }
这里有两个考点:1类型转化问题,2操作符优先级问题。
~优先级要高于>>和+优先级,而+高于>>和其他位运算符的优先级。所以代码第5行先执行按位取反操作,然后将a向右移5位。
注意还有一个类型提升问题,在运算中,会将所有小于整形的有序类型被转化成整型,因此在计算机的表示为a=0x00A5,取反操作后变成了0xff5A,右移5位变成0xfffa(注意这里高位是补1而非0)。但是后又赋值给char类型的b,截取低8位b=0xfa,然后按整数类型输出为250。
(a&b) + ((a^b)>>1)表示求a、b的平均值。可以这么理解,a&b表示将a和b相同位相加,再向右移一位,即相同位的一半。(a^b)>>1表示不同位的一半,然后再相加,即为a和b的平均值。
不用中间变量交换两个整数的值:
a=a+b; b=a-b; a=a-b; //优点:不仅仅只适合整数。缺点:可能导致溢出的问题。
a=a^b; b=a^b; a=a^b; //优点:不会溢出。缺点:只适合整数类型
int max = (a+b + abs(a-b))/2。 //获得a、b两个整数的较大值。不用判断语句。
计算机预处理将会为我们计算出常量表达式的值。因此若定义一年中的秒数,建议这么写:#define SECONDS_ONE_YEAR (60*60*24*365)UL
C++类中,想要在const修饰的成员函数修改类变量,需要在改变量前加上mutable。
class A{ public: void fun() const{ count++; } private: mutable int count; }
sizeof问题。
默认情况下,为了方便对结构体内元素的访问和管理,当结构体内的元素长度都小于处理器的位数的时候,便以结构体内最长的元素为对齐单位,即结构体的长度一定是最长元素的整数倍。若结构体内存在长度大于处理器位数的元素,那么以处理器的位数为对其单位(默认为8字节对齐)。结构体内类型相同的连续元素将在连续空间内。
下面举个例子:
struct A{ short a1; char c1; long a4; short a2; };
上述代码中,最长元素为long类型,占用四个字节,小于默认的8字节,因此对齐单位为4。a1占用两个字节,放在第一个对齐单元中。c1占用1个字节,而上一个对齐单元还剩两个字节,能放下,因此放在第一个对齐单元中。a4占用4个字节,上一个对齐单元还剩一个字节,不能放下,因此放在下一个对齐单元中。a2占用2个字节,上一个对齐单元还剩0个字节,因此放在下一个对齐单元中。因此总共占用了三个对齐单元,每个对齐单元为4个字节,sizeof(A)=3*4=12
对于类的成员函数,在计算sizeof的时候,无需考虑成员函数的空间。静态成员放在全局存储区,因此也无需考虑。
sizeof()中括号内的内容在编译过程中是不被编译的,而是被替代类型。如:int a=8; sizeof(a=6); 结果相当于int a=8; sizeof(int); 即a的值不变,仍是6。
sizeof空类==1;若一个类中有virtual函数,不管virtual函数有多少个,都只有一个指针,sizeof包含若干virtual函数的类==4
虚继承,能够解决菱形继承问题。详细的虚继承见:http://zh.wikipedia.org/wiki/%E8%99%9A%E7%BB%A7%E6%89%BF
面向对象技术的基本概念是:对象、类和继承
C++中的空类默认产生的成员函数有:默认构造函数、析构函数、拷贝构造函数和赋值函数
赋值函数是重载=操作符的函数。在定义时赋值调用的是拷贝构造函数。其他地方调用的是赋值函数。
成员初始化列表的初始化列表的变量顺序是根据成员变量的声明顺序执行的。多继承中,父类的构造函数执行顺序与继承列表的顺序一致。
c++默认的继承方式是private,所以一定要记得写public
虚指针即为虚函数指针,带有虚函数的类中的每一个对象都有一个虚指针指向该类的虚函数表。
C++中如何阻止一个类被实例化?
使用抽象类或者将构造函数申明为private
扩展:将构造函数申明为private,能够防止外部产生类的实例。将拷贝构造函数或者赋值构造函数声明为private,能阻止外部对这个类进行赋值操作。
RTTI,Run Time Type Infomation,运行时类型信息,包括dynamic_cast和typeid。
printf("%f", 5);printf("d", 5.01);输出是什么?分别是0.000000和一个很大的整数。
初始序列为1 8 6 2 5 4 7 3一组数采用堆排序,当建堆(小根堆)完毕时,堆所对应的二叉树中序遍历序列为:(A)
A. 8 3 2 5 1 6 4 7
B.3 2 8 5 1 4 6 7
C.3 8 2 5 1 6 7 4
D.8 2 3 5 1 4 7 6
注意堆排序的建堆的时候是从下标为len/2的元素shiftdown的过程,而不是shiftup。
0 条评论