c++ 面经(1) ------ 面经之基础知识
2018-03-04 16:43
204 查看
自己写的面经,也是找了一段时间,现在总结出来遇见的以及可能遇见的。还有些经常会被问到的。都总结出来以供大家参考。
基础知识
1.常用的类型范围
int -2147483648 ~ +2147483647 (4 Bytes)
unsigned int 0 ~ 4294967295 (4 Bytes)
char -128 ~ +127 (1 Bytes)
short -32767 ~ +32768 (2 Bytes)
unsigned short 0 ~ 65536 (2 Bytes)
long == int
long long -9223372036854775808 ~ +9223372036854775807 (8 Bytes)
double 1.7 * 10^308 (8 Bytes)
float小数点前后加起来有效数字只有6位
double 小数点后面有效数字16位
2.计算机 -大端小端问题
大端小端是高地地址问题,大端是高地址在前,小端是低地址在前。跟cpu有关。
我们常用的X86结构是小端模式,而KEIL C51则为大端模式。很多的ARM,DSP都为小端模式。
其实大端小端是个多字节排序的问题。
3.sizeof strlen问题
sizeof() 是一个判断数据类型或者表达式长度的运算符
sizeoof(char*) 指的是所占的字节数 ----注意32、64位系统
strlen() --- 计算的是字符串的长度
4.堆和栈、堆和栈访问速度谁快、new和malloc的区别(new比malloc多些什么,在申请或者释放多了那些)
堆和栈:
堆的内存增长方向是自低向高处的增长。低 ->高 增长。
栈的内存增长方向是自高向低增长。高 ->低 增长。----- 因为栈内存都是系统分配的可以理解为分配的空间是连续的。
在malloc多次申请时,malloc会内存不同位置申请连续的空间,所以容易造成内存碎片化。
堆和栈在访问速度上,栈更快。原因如下:
(1).分配和释放,堆在分配和释放都要调用函数(malloc,free),去内存寻找到足够大小的空间。这些栈都不需要。
(2).访问时间,正常访问堆时需要两次操作,第一次获取指针,第二步取相应数据。而栈只需要访问一次就可以取到内容。
(3).栈有专门寄存器,压栈和出栈很快,而堆需要os动态调整。
分配方式上,堆是动态分配的,栈是编译器完成的。
new和malloc的区别(new比malloc多些什么,在申请或者释放多了那些):
new和malloc的区别是C/C++一道经典的面试题 ---- 需要注意
(1).属性:
new/delete是C++关键字,需要编译器支持。malloc/free是库函数,需要头文件支持。
(2).参数:
使用new操作符申请内存分配时无须指定内存块的大小,编译器会根据类型信息自行计算。而malloc则需要显式地指出所需内存的尺寸
(3).返回类型:
new操作符内存分配成功时,返回的是对象类型的指针,类型严格与对象匹配,无须进行类型转换,故new是符合类型安全性的操作符。而malloc内存分配成功则是返回void * ,需要通过强制类型转换将void*指针转换成我们需要的类型。
(4).分配失败:
new内存分配失败时,会抛出bac_alloc异常。malloc分配内存失败时返回NULL。
(5).自定义类型:
new会先调用operator new函数,申请足够的内存(通常底层使用malloc实现)。然后调用类型的构造函数,初始化成员变量,最后返回自定义类型指针。delete先调用析构函数,然后调用operator delete函数释放内存(通常底层使用free实现)。
malloc/free是库函数,只能动态的申请和释放内存,无法强制要求其做自定义类型对象构造和析构工作。
(6).重载:
C++允许重载new/delete操作符,特别的,布局new的就不需要为对象分配内存,而是指定了一个地址作为内存起始区域,new在这段内存上为对象调用构造函数完成初始化工作,并返回此地址。而malloc不允许重载。
(7).内存区域:
new操作符从自由存储区(free store)上为对象动态分配内存空间,而malloc函数从堆上动态分配内存。自由存储区是C++基于new操作符的一个抽象概念,凡是通过new操作符进行内存申请,该内存即为自由存储区。而堆是操作系统中的术语,是操作系统所维护的一块特殊内存,用于程序的内存动态分配,C语言使用malloc从堆上分配内存,使用free释放已分配的对应内存。自由存储区不等于堆,如上所述,布局new就可以不位于堆中。
(8) C++内存管理方式:
堆、栈、自由存储区、全局\\静态存储区、常量存储区
自由存储区,就是那些由malloc等分配的内存块,他和堆是十分相似的,不过它是用free来结束自己的生命的。
自由存储区//堆:free 和malloc用在堆上,有些编译器中new和delete用的是free和malloc去申请的内存在堆上,但是如果通过重载操作符,改变其他内存实现自由存储,例如全局变量做的对象池,这时自由存储区就区别于堆了。堆与自由存储区并不完全等价
5.const的应用
指针常量 const int *p: p是一个指针,指向const int,表示的意义就是不能通过p来修改p指向的值,而p本身所指向的地址是可以修改的。(此处也可以写成int const *p是一样的)
常量指针 int* const p: 表示p本身是一个const,所以p所指的地址不会变,但是地址里的值是可以修改的。
const int *x const在*前面,该数据不能改变
int* const y const在地址前面,该地址不能变化
6.常用的c函数和头文件,memcpy、memcmp、strcmp、strncmp、strcpy、strncpy
memcpy:
memcpy ==> c 语言 #include <string.h>
==> c++ #include<cstring>
memcmp:
memcmp(const void *buf1, const void *buf2, unsigned int count);
比较内存区域buf1和buf2的前count个字节。
返回值:
当buf1<buf2时,返回值<0当buf1=buf2时,返回值=0当buf1>buf2时,返回值>0==> 头文件 #include<string.h>
strcmp:
头文件 #include<string.h>
设这两个字符串为str1,str2,
若str1==str2,则返回零;
若str1<str2,则返回负数;
若str1>str2,则返回正数
strncmp:
头文件 #include<string.h>
int strncmp ( const char * str1, const char * str2, size_t n );
比较s1和s2字符串,如果字符串s1与s2的前size个字符相同,函数返回值为0。
strcpy/strncpy:
头文件 #include<string.h>
strcpy 计算长度等等字符串处理,都是自动到’\0’字符。
strncpy 若a未初始化,未拷贝赋值的后半a全部赋值0,即空字符’\0’。若a已初始化,未拷贝赋值的后半a依然保持原样。
7. c和c++ 头文件的区别
#include <stdio.h> c头文件
#inlcude <cstdio> c++头文件
8. 关键字 static、extern、inline、volatile
static:
static 结果保存在全局数据区(静态区)
static 静态局部变量,函数结束后其中的变量并没有消失,而是在整个程序结束后才会消失。
extern:
(1) extern 如果和c连接在一起用。如: extern "C" void fun(int a, int b);则告诉编译器在编译fun这个函数名时按着C的规则去翻译相应的函数名而不是C++的,C++的规则在翻译这个函数名时会把fun这个名字变得面目全非,可能是fun@aBc_int_int#%$也可能是别的
(2) extern 不和c一起用,如在头文件中: extern int g_Int; 它的作用就是声明函数或全局变量的作用范围的关键字,其声明的函数和变量可以在本模块活其他模块中使用
inline:
为了解决一些频繁调用的小函数大量消耗栈空间(栈内存)的问题,特别的引入了inline修饰符,表示为内联函数。栈空间就是指放置程序的局部数据(也就是函数内数据)的内存空间
在系统下,栈空间是有限的,假如频繁大量的使用就会造成因栈空间不足而导致程序出错的问题
优点:使用内联函数,效率高,运行快。
使用条件:
内联编译的建议性由编译器决定。
逻辑简单调用频繁的函数,建议使用内联函数。
递归函数无法使用内联函数。
volatile:
嵌入式编程应用:
(1) 告诉compiler不能做任何优化
比如要往某一地址送两指令:
(2)表示用volatile定义的变量会在程序外被改变,每次都必须从内存中读取,而不能把他放在cache或寄存器中重复使用。
易变性。所谓的易变性,在汇编层面反映出来,就是两条语句,下一条语句不会直接使用上一条语句对应的volatile变量的寄存器内容,而是重新从内存中读取。如:
此例转自:http://blog.csdn.net/k346k346/article/details/46941497这个对于volatile说的很详细很好推荐 转载:http://blog.csdn.net/c359719435/article/details/51490060
设计出来的C/C++ Volatile关键词,所含有的特性,三个特性:易变性;不可优化性;顺序性。
基础知识
1.常用的类型范围
int -2147483648 ~ +2147483647 (4 Bytes)
unsigned int 0 ~ 4294967295 (4 Bytes)
char -128 ~ +127 (1 Bytes)
short -32767 ~ +32768 (2 Bytes)
unsigned short 0 ~ 65536 (2 Bytes)
long == int
long long -9223372036854775808 ~ +9223372036854775807 (8 Bytes)
double 1.7 * 10^308 (8 Bytes)
float小数点前后加起来有效数字只有6位
double 小数点后面有效数字16位
2.计算机 -大端小端问题
大端小端是高地地址问题,大端是高地址在前,小端是低地址在前。跟cpu有关。
我们常用的X86结构是小端模式,而KEIL C51则为大端模式。很多的ARM,DSP都为小端模式。
其实大端小端是个多字节排序的问题。
3.sizeof strlen问题
sizeof() 是一个判断数据类型或者表达式长度的运算符
sizeoof(char*) 指的是所占的字节数 ----注意32、64位系统
strlen() --- 计算的是字符串的长度
4.堆和栈、堆和栈访问速度谁快、new和malloc的区别(new比malloc多些什么,在申请或者释放多了那些)
堆和栈:
堆的内存增长方向是自低向高处的增长。低 ->高 增长。
栈的内存增长方向是自高向低增长。高 ->低 增长。----- 因为栈内存都是系统分配的可以理解为分配的空间是连续的。
在malloc多次申请时,malloc会内存不同位置申请连续的空间,所以容易造成内存碎片化。
堆和栈在访问速度上,栈更快。原因如下:
(1).分配和释放,堆在分配和释放都要调用函数(malloc,free),去内存寻找到足够大小的空间。这些栈都不需要。
(2).访问时间,正常访问堆时需要两次操作,第一次获取指针,第二步取相应数据。而栈只需要访问一次就可以取到内容。
(3).栈有专门寄存器,压栈和出栈很快,而堆需要os动态调整。
分配方式上,堆是动态分配的,栈是编译器完成的。
new和malloc的区别(new比malloc多些什么,在申请或者释放多了那些):
new和malloc的区别是C/C++一道经典的面试题 ---- 需要注意
(1).属性:
new/delete是C++关键字,需要编译器支持。malloc/free是库函数,需要头文件支持。
(2).参数:
使用new操作符申请内存分配时无须指定内存块的大小,编译器会根据类型信息自行计算。而malloc则需要显式地指出所需内存的尺寸
(3).返回类型:
new操作符内存分配成功时,返回的是对象类型的指针,类型严格与对象匹配,无须进行类型转换,故new是符合类型安全性的操作符。而malloc内存分配成功则是返回void * ,需要通过强制类型转换将void*指针转换成我们需要的类型。
(4).分配失败:
new内存分配失败时,会抛出bac_alloc异常。malloc分配内存失败时返回NULL。
(5).自定义类型:
new会先调用operator new函数,申请足够的内存(通常底层使用malloc实现)。然后调用类型的构造函数,初始化成员变量,最后返回自定义类型指针。delete先调用析构函数,然后调用operator delete函数释放内存(通常底层使用free实现)。
malloc/free是库函数,只能动态的申请和释放内存,无法强制要求其做自定义类型对象构造和析构工作。
(6).重载:
C++允许重载new/delete操作符,特别的,布局new的就不需要为对象分配内存,而是指定了一个地址作为内存起始区域,new在这段内存上为对象调用构造函数完成初始化工作,并返回此地址。而malloc不允许重载。
(7).内存区域:
new操作符从自由存储区(free store)上为对象动态分配内存空间,而malloc函数从堆上动态分配内存。自由存储区是C++基于new操作符的一个抽象概念,凡是通过new操作符进行内存申请,该内存即为自由存储区。而堆是操作系统中的术语,是操作系统所维护的一块特殊内存,用于程序的内存动态分配,C语言使用malloc从堆上分配内存,使用free释放已分配的对应内存。自由存储区不等于堆,如上所述,布局new就可以不位于堆中。
(8) C++内存管理方式:
堆、栈、自由存储区、全局\\静态存储区、常量存储区
自由存储区,就是那些由malloc等分配的内存块,他和堆是十分相似的,不过它是用free来结束自己的生命的。
自由存储区//堆:free 和malloc用在堆上,有些编译器中new和delete用的是free和malloc去申请的内存在堆上,但是如果通过重载操作符,改变其他内存实现自由存储,例如全局变量做的对象池,这时自由存储区就区别于堆了。堆与自由存储区并不完全等价
5.const的应用
指针常量 const int *p: p是一个指针,指向const int,表示的意义就是不能通过p来修改p指向的值,而p本身所指向的地址是可以修改的。(此处也可以写成int const *p是一样的)
常量指针 int* const p: 表示p本身是一个const,所以p所指的地址不会变,但是地址里的值是可以修改的。
const int *x const在*前面,该数据不能改变
int* const y const在地址前面,该地址不能变化
6.常用的c函数和头文件,memcpy、memcmp、strcmp、strncmp、strcpy、strncpy
memcpy:
memcpy ==> c 语言 #include <string.h>
==> c++ #include<cstring>
memcmp:
memcmp(const void *buf1, const void *buf2, unsigned int count);
比较内存区域buf1和buf2的前count个字节。
返回值:
当buf1<buf2时,返回值<0当buf1=buf2时,返回值=0当buf1>buf2时,返回值>0==> 头文件 #include<string.h>
strcmp:
头文件 #include<string.h>
设这两个字符串为str1,str2,
若str1==str2,则返回零;
若str1<str2,则返回负数;
若str1>str2,则返回正数
strncmp:
头文件 #include<string.h>
int strncmp ( const char * str1, const char * str2, size_t n );
比较s1和s2字符串,如果字符串s1与s2的前size个字符相同,函数返回值为0。
strcpy/strncpy:
头文件 #include<string.h>
strcpy 计算长度等等字符串处理,都是自动到’\0’字符。
strncpy 若a未初始化,未拷贝赋值的后半a全部赋值0,即空字符’\0’。若a已初始化,未拷贝赋值的后半a依然保持原样。
7. c和c++ 头文件的区别
#include <stdio.h> c头文件
#inlcude <cstdio> c++头文件
8. 关键字 static、extern、inline、volatile
static:
static 结果保存在全局数据区(静态区)
static 静态局部变量,函数结束后其中的变量并没有消失,而是在整个程序结束后才会消失。
extern:
(1) extern 如果和c连接在一起用。如: extern "C" void fun(int a, int b);则告诉编译器在编译fun这个函数名时按着C的规则去翻译相应的函数名而不是C++的,C++的规则在翻译这个函数名时会把fun这个名字变得面目全非,可能是fun@aBc_int_int#%$也可能是别的
(2) extern 不和c一起用,如在头文件中: extern int g_Int; 它的作用就是声明函数或全局变量的作用范围的关键字,其声明的函数和变量可以在本模块活其他模块中使用
inline:
为了解决一些频繁调用的小函数大量消耗栈空间(栈内存)的问题,特别的引入了inline修饰符,表示为内联函数。栈空间就是指放置程序的局部数据(也就是函数内数据)的内存空间
在系统下,栈空间是有限的,假如频繁大量的使用就会造成因栈空间不足而导致程序出错的问题
优点:使用内联函数,效率高,运行快。
使用条件:
内联编译的建议性由编译器决定。
逻辑简单调用频繁的函数,建议使用内联函数。
递归函数无法使用内联函数。
volatile:
嵌入式编程应用:
(1) 告诉compiler不能做任何优化
比如要往某一地址送两指令:
int *ip =...; //设备地址 *ip = 1; //第一个指令 *ip = 2; //第二个指令以上程序compiler可能做优化而成:
int *ip = ...; *ip = 2;结果第一个指令丢失。如果用volatile, compiler就不允许做任何的优化,从而保证程序的原意:
volatile int *ip = ...; *ip = 1; *ip = 2;即使你要compiler做优化,它也不会把两次赋值语句间化为最后一句,它只能做其它的优化。这对device driver程序员很有用。
(2)表示用volatile定义的变量会在程序外被改变,每次都必须从内存中读取,而不能把他放在cache或寄存器中重复使用。
易变性。所谓的易变性,在汇编层面反映出来,就是两条语句,下一条语句不会直接使用上一条语句对应的volatile变量的寄存器内容,而是重新从内存中读取。如:
volatile char a; a=0; while(!a) { //do some things; } doother();如果没有 volatile,doother()不会被执行
此例转自:http://blog.csdn.net/k346k346/article/details/46941497这个对于volatile说的很详细很好推荐 转载:http://blog.csdn.net/c359719435/article/details/51490060
设计出来的C/C++ Volatile关键词,所含有的特性,三个特性:易变性;不可优化性;顺序性。
相关文章推荐
- 关于C++程序设计的基础核心之二:继承与派生的基本知识
- C++之基础知识学习笔记
- C++基础知识复习之--顺序表学生成绩管理系统
- C++基础知识之vector
- C++ 基础知识目录
- C++ 基础知识
- C语言/C++基础知识
- C/C++基础知识总结——数据的共享与保护
- 需要注意的c++ 的11个要点[转贴] 基础知识
- C++基础知识之struct和class的区别
- C/C++内存管理和指针基础知识2
- C++基础知识容易忽略的知识点
- C++基础知识实例解析(一)
- c++基础知识(容易面试到的)
- C++容易被忽视的基础知识
- QT最简单的程序执行过程分析(内含C++基础知识)
- C++顺序容器基础知识总结
- C++ 顺序容器基础知识总结
- C++基础知识2
- C++基础知识:友元