程序员面试宝典 知识点总结

1 篇文章 0 订阅

1.C语言,printf计算参数是是从右向左计算的,如printf("%d,%d\n",a++,b++)   此时,先计算b++,然后计算a++。

2.x&y+(x^y>>2)  表示x于y的平均数。分为三部分,第一部分是两个数二进制均为1的位,&后还为1,相当于取和后除以2。第二部分,两个数有一个为1的位相加,然后右移两位相当于除以二,第三部分,全为0的部分,取和无意义。所以最后是两个数的平均数。

3.不用if switch ?: 或其他判断语句实现判断a b的大小  :((a+b)+abs(a-b))/2;

4.memcpy(void*dest, const void*src,unsigned int count);   由src所指内存区域复制count个字节到dest所指内存区域

5.const int *a=&b  与  int const *a =&b   是一样效果,const在 * 的左边,既指针所指向的内容为常量,既后面改变*a的值是错误的  *a=600 是错误的。

int * const a=&b ,这种情况必须初始化, 指针本身的常量 ,既 a++  是错误的。

const int * const a=&b    都是常量,都不可以改变。

6.位运算要比乘除法取余等小效率高得多,乘以2:a<<1, 除以2: a>>1  判读一个数是奇是偶:a&0x1==1   说明是奇数 

7.表达式中如果有无符号数和有符号数,有符号数自动转换成无符号

8.extern "c"    而加上extern "C"后,是为了向编译器指明这段代码按照C语言的方式进行编译,解决名字匹配问题 

<1. 可以是单一语句

    extern "C" double sqrt(double);

<2. 可以是复合语句, 相当于复合语句中的声明都加了extern "C"

    extern "C"

   {

      double sqrt(double);

      int min(int, int);

  }

<3.可以包含头文件,相当于头文件中的声明都加了extern "C"

   extern "C"

  {

    #include <cmath>

  }

9.

main()函数执行完后,还会调用执行其他的语句吗?

全局对象的构造函数会在main函数之前执行。

       我们通常认为C语言的起始函数是main()函数,实质上一个程序的启动函数并不一定是main()函数,这个可以采用链接器来设置,但是gcc中默认main()就是C语言的入口函数,在main函数启动之前,内核会调用一个特殊的启动例程,这个启动例程从内核中取得命令行参数值和环境变量值,为调用main()函数做好准备。

      因此对应程序而言main()函数并不是起始,但是对应C 语言而言,main()函数就是入口地址。

      按照ISO C的规定,一个进程可以登记多达32个函数,这些函数将由exit自动调用,通常这32个函数被称为终止处理程序,并调用atexit()函数来登记这些函数。 (函数的调用顺序与注册的顺序是相反的,通过下面的实例可以看出来)     

9.extern是计算机语言中的一个关键字,可置于变量或者函数前,以表示变量或者函数的定义在别的文件中 ,在一个文件中声明全局变量int a=1,在别的文件中用extern  a   就可以调用该全局变量

10.char str[]="hello";     sizeof(str)=6   是整个数组的大小。   当传入函数参数中时,

void fun(char str[]){

sizeof(str)=4                       退化成了指针

}

10、sizeof 和 strlen 的区别:

<1.    Strlen 是函数,strlen(char*)函数求的是字符串的实际长度,直到遇到第一个'\0',然后就返回计数值,且不包括'\0',函数的返回值值在运行时确定。参数是指针或字符数组,当数组名作为参数传入时,实际上数组就退化成指针了。

 

<2.      Sizeof是操作符,不是函数,返回的是变量声明后所占的内存数,不是实际长度。其值在编译时即计算好了,参数可以是数组、指针、类型、对象、函数等。当计算数组的size时,数组不会退化成指针。

11.联合体和结构体

联合体
用途:使几个不同类型的变量共占一段内存(相互覆盖)

结构体是一种构造数据类型
用途:把不同类型的数据组合成一个整体-------自定义数据类型

主要区别:

1. struct和union都是由多个不同的数据类型成员组成, 但在任何同一时刻, union中只存放了一个被选中的成员, 而struct的所有成员都存在。在struct中,各成员都占有自己的内存空间,它们是同时存在的。一个struct变量的总长度等于所有成员长度之和。在Union中,所有成员不能同时占用它的内存空间,它们不能同时存在。Union变量的长度等于最长的成员的长度。

2. 对于union的不同成员赋值, 将会对其它成员重写, 原来成员的值就不存在了, 而对于struct的不同成员赋值是互不影响的。

12.内联函数  像宏定义一样做符号的替换,没有了函数压栈等操作,效率很高。但是他是一个函数,也会有调用之前的函数类型,函数参数等一系列的检查,保证其正确性,这是内联函数比宏定义的优势所在。而且还能定义成类的成员函数,可以定义成私有或保护成员,隐私性更高

13.如何交换两个字符串:用到指针的指针或者指针的引用   

void swap (char*&a, char*&b)

{ char* temp; temp=a; a=b; b=temp; }

或者 void swap(char **a,char**b){ char*temp; temp=*a; *a=*b; *b=*temp;  }

14.有const 的常量类型的变量,它的引用必须是常量(const)。为常量类型的变量,它的引用既可以是常量,又可以是非常量。

15.指针的加减操作  int a[5]={1,2,3,4,5}    a值的是数组第一个元素的地址   &a 指的是数组的首地址      *(a+1)是2      *(&a+1) 是5的下一个位置  越界了

 

16。int b; //栈      char s[] = "abc"; //栈         char *p2; //栈       char *p3 = "123456";       //”123456“”在常量区,p3在栈上

常量存储区也叫字符串常量区,用于存放字符串常量,在对字符串赋值时,会在字符串常量区开辟一块空间来存储对应的字符串常量,然后返回这块空间的首地址。

17.char* strcpy(char* strto,char* strfrom)      和   void* memcpy(void* to ,void *from,size_t num)     size_t它是一种“整型”类型,里面保存的是一个整数,就像int, long那样。这种整数用来记录一个大小(size)。size_t的全称应该是size type,就是说“一种用来记录大小的数据类型”。         strcpy 是字符串拷贝  遇到/0 结束。       memcpy是任何类型的拷贝num个字符;

18.strcmp     C/C++函数,比较两个字符串设这两个字符串为str1,str2,若str1==str2,则返回零;若str1<str2,则返回负数;若str1>str2,则返回正数。

19.static的作用:  <1 >c++ 中,静态数据成员:在类外单独初始化,无论实例化多少对象,静态成员变量只有一个,由所有对象共享。储存在全局变量区。静态成员函数:无this指针,无法访问非静态的变量或函数。

   <2> 在函数体内的静态变量,在函数调用中值不变。在函数体外,模块内定义的静态变量是一个本地的全局变量,只能被模块内 的函数访问。在模块内的静态函数,只能被模块内的其他函数调用,只能在本地范围能使用。

20.单精度浮点数float 4字节和双精度浮点数 double 8字节    储存方式都是 符号位,指数位  尾数位 的方式储存,都是将十进制化成二进制方式储存的,小数部分化成二进制有时会化不尽,有截断误差的存在。

21.关联容器和顺序容器有着根本的不同:关联容器中的元素是按关键字来保存和访问的。与之相对,顺序容器中的元素是按它们在容器中的位置来顺序保存和访问的。关联容器支持高效的关键字查找与访问。两个主要的关联容器类型是map与set。

22.正则表达式  两个特殊的符号'^'和'$'。他们的作用是分别指出一个字符串的开始和结束

23 出栈的可能次数记住公式: C(2n,n)/(n+1)

24.ipv6 地址128位  ipv4地址是32位

25 死锁 :某系统中有3个并发进程,都需要同类资源4 个,试问该系统不会发生死锁的最少资源数是? 在本题目中,当有三个并发进程同时对资源进行申请时,最可能发生死锁的情况是三个进程当前各自都占据了3个资源,此时,只再需要1个该类资源,即可以在这种情况下不发生死锁。

26.

<1、栈区(stack)—  由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。  
< 2、堆区(heap) —  一般由程序员分配释放,若程序员不释放,程序结束时可能由OS(操作系统)回收。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。  
<3、全局区(静态区)(static)—全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后由系统释放。  
<4、文字常量区  —常量字符串就是放在这里的。程序结束后由系统释放。
<5、程序代码区—存放函数体的二进制代码。  

<6.自由存储区,只是一个概念,由new 生成的对象的存储位置就是自由存储区。他可以是堆,也可以是栈。

27.static局部变量与普通局部变量的的区别:静态局部变量只能初始化一次,下一次的值根据上一次的结果。

     static全局变量与普通全局变量的的区别:静态全局变量只能在该源文件(.cpp)中使用,而全局变量可在该源程序的所有原文件         中使用。

      static函数与函数的的区别:静态函数在内存中只有一份,而普通函数每个调用中都有一份复制品。

      静态成员变量,不依靠对象,只依靠类,有所有实例化对象共享,在类外初始化。普通成员变量,实例化一次就复制一次。

      静态成员函数:无this指针,所以不能调用非静态成员

28.类:从客观对象中抽象出的一个一般的概念   对象:是类的实例或实体。   封装继承多态

            <1>在C++中,比较狭隘的解释就是将数据与操作数据的方法放在一个类中,而后给每个成员设置相应的权限。从大一点的角度来说,封装就是将完成一个功能所需要的所有东西放在一起,对外部只开放调用它的接口。

<2>多态简单的说就是“一个函数,多种实现”,或是“一个接口,多种方法”。多态性表现在程序运行时根据传入的对象调用不同的函数。 C++的多态是通过虚函数来实现的,在基类中定义一个函数为虚函数,该函数就可以在运行时,根据传入的对象调用不同的实现方法。而如果该函数不设为虚函数,则在调用的过程中调用的函数就是固定的。

<2>很多人说继承可以使代码得到良好的复用,当然这个是继承的一个优点,但代码复用的方法除了继承还有很多,而且有些比继承更好。我认为使用继承最重要的原因是继承可以使整个程序设计更符合人们的逻辑,从而方便的设计出想要表达的意思。比如我们要设计一堆苹果,橘子,梨等水果类,使用面向对象的方法,我们首先会抽象出一个水果的基类,而后继承这个基类,派生出具体的水果类。如果要设计的水果很多,我们还可以在水果基类基础上,继续生成新的基类,比如热带水果类,温带水果类,寒带水果类等,而后再继承这些基类。这样的设计思想就相当于人类的分类思想,简单易懂,而且设计出来的程序层次分明,容易掌握。

29.必须使用初始化列表的情况:

        1. 如果类中有一个成员是一个引用, 由于引用必须给予初始值, 因此, 引用必须使用初始化列表.	
	2. 同理, const属性必须给予初始值, 必须使用初始化列表.	
	3. 继承类中调用基类初始化构造函数, 实际上就是先构造基类对象, 必须使用初始化列表.

30.sizeof(空类) 为一个字节      有虚函数 为4个字节  虚函数表

31.空类的默认成员函数: 构造函数 析构函数   拷贝构造函数   赋值函数(同类对象赋值)  取值运算(&取地址时)

32.虚析构函数 不引入虚析构函数是,用父类的指针指向子类对象,当delete销毁父类指针时,不会调用子类的析构函数,可能会        造成内存泄漏,引入虚析构函数,父类delete,先调用子类的析构函数,再调用父类的析构函数,避免了内存泄漏。

33.虚继承:解决菱形继承的基类数据冗余的问题。

34.构造函数的顺序:首先调用基类的构造函数,然后调用成员对象(类中的数据成员是个对象)的构造函数(按声明顺序而不是初始化列表的顺序),

35.浅拷贝与深拷贝:当没有定义拷贝构造函数时,拷贝对象调用的是默认的拷贝构造函数,只是把对象里的值完全复制给另一个对象,是浅拷贝。A=B,当B中有一个成员变量是指针,已经申请了内存,浅拷贝只是让B中的那个指针成员变量和A中的指针指向同一段内存,这时B内存释放后,A中的指针就变成了野指针,出现错误。所以要用到深拷贝,重新开辟一段内存,将A的指针所指的内容复制进去。这两个指针是两个不同的地址。

36,为什么c不能重载:函数重载是相同函数名,参数个数或类型不同,实现相似的功能。在c++中,编译器处理函数后包含了函数的原函数名,返回类型,参数数量和类型等,int fun(int ,int )  变成   _int_fun_int_int     而c语言不会对函数名进行处理。

37.函数覆盖和隐藏:主动覆盖,被动隐藏。   隐藏是子类具有和父类相同函数名的函数,但参数,返回值可以不同,和父类函数实现不同的功能,父类函数被隐藏。 覆盖是父类函数有virtual 是虚函数,子类该函数与父类函数相同,但实现功能不同,用父类指针指向子类的对象,调用该函数是,父类的该函数被覆盖,也就是实现了多态的功能。

38.虚函数表:类内如果有虚函数,那么类在内存中会有一个虚函数表指针,指向虚函数表。虚函数表中储存着所有的虚函数的位置,如果子类中没有定义与父类同名的虚函数,那么子类的虚函数表会把父类的虚函数表复制过来。如果子类定义与父类同名的虚函数,那该地址就覆盖成了子类的虚函数地址,称为函数覆盖。

39.不能重载的运算符只有5个:. (成员访问运算符).* (成员指针访问运算符)::  (域运算符)sizeof (长度运算符)?:  (条件运算符)

40.c++ 运算符重载有时返回值是类的引用。目的是能够进行连续赋值。  A &(this) operator=(const A & a) {   。。。。 return  *this;      }     不加引用时,要定义一个临时变量:

Box operator+(const Box& b)

{ Box box;

box.length = this->length + b.length;

box.breadth = this->breadth + b.breadth;

box.height = this->height + b.height;

return box; }

41.对多态的理解:同一操作作用于不同的对象,可以产生不同的结果。  是一种动态绑定,在运行时决定操作哪一个函数。

 利用虚函数实现,通过父类的指针或引用指向子类,来实现子类函数的功能。

42.虚函数的使用限制:1.不能修饰构造函数。2.不能修饰静态成员函数。 3.不能修饰内联函数。4.不能修饰普通函数,只能修饰类的成员函数。

43.为什么选函数不能为构造函数:在构造函数中,虚拟机制不会发生作用。因为基类的构造函数在子类的构造函数之前执行,如果基类的构造函数向下调用子类的构造函数会涉及到子类的数据成员,但这些数据还没有被初始化。

44.<1>多继承是指一个子类继承多个父类。多继承对父类的个数没有限制。

     <2> 多重继承特点总结如下:

(1)多重继承与多继承不同,当B类从A类派生,C类从B类派生,此时称为多重继承

(1)当实例化子类时,会首先依次调用所有基类的构造函数,最后调用该子类的构造函数;销毁该子类时,则相反,先调用该子类的析构函数,再依次调用所有基类的析构函数。

(2)无论继承的层级有多少层,只要它们保持着直接或间接的继承关系,那么子类都可以与其直接父类或间接父类构成 is a的关系,并且能够通过父类的指针对直接子类或间接子类进行相应的操作,子类对象可以给直接父类或间接父类的对象或引用赋值或初始化。

45.用虚拟继承解决菱形继承的二义性的问题。

46.c与c++的区别   区别一:重载问题   c++可进行重载,函数名相同,参数类型或参数个数不同,执行不同的内容。区别二:               struct的功能:我们都知道在C和C++代码中都可以定义结构体struct,然而C语言只能在struct中声明变量(像int类型,char类型),但是C++语言不仅可在struct中声明变量,同时还可以定义函数,优点类似于类的既可以有成员变量又有方法。区别三:c++支持面向对象编程

47.面向对象与面向过程的区别:面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。 面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为,具有更好的可移植性和可扩展性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值