十八万字整理C/C++、嵌入式软开 常见面试题汇总25
十八万字吐血整理的C/C++、嵌入式常见面试题!!!!
文中很多资料避免不了从网上或是其他复习资料里收集整理,十分感谢前辈的辛勤付出,如果存在侵权请一定联系我进行删除。
系列文章PDF下载地址:《最全C_C++及嵌入式软开面试题宝典.pdf》
151、动态编译与静态编译
1.静态编译,编译器在编译可执行文件时,把需要用到的对应动态链接库中的部分提取出来,连接到可执行文件中去,使可执行文件在运行时不需要依赖于动态链接库;
2.动态编译的可执行文件需要附带一个动态链接库,在执行时,需要调用其对应动态链接库的命令。所以其优点一方面是缩小了执行文件本身的体积,另一方面是加快了编译速度,节省了系统资源。缺点是哪怕是很简单的程序,只用到了链接库的一两条命令,也需要附带一个相对庞大的链接库;二是如果其他计算机上没有安装对应的运行库,则用动态编译的可执行文件就不能运行。
152、动态链接和静态链接区别
1.静态连接库就是把(lib)文件中用到的函数代码直接链接进目标程序,程序运行的时候不再需要其它的库文件;动态链接就是把调用的函数所在文件模块(DLL)和调用函数在文件中的位置等信息链接进目标程序,程序运行的时候再从DLL中寻找相应函数代码,因此需要相应DLL文件的支持。
2.静态链接库与动态链接库都是共享代码的方式,如果采用静态链接库,则无论你愿不愿意,lib 中的指令都全部被直接包含在最终生成的 EXE 文件中了。但是若使用 DLL,该 DLL 不必被包含在最终 EXE 文件中,EXE 文件执行时可以“动态”地引用和卸载这个与 EXE 独立的 DLL 文件。静态链接库和动态链接库的另外一个区别在于静态链接库中不能再包含其他的动态链接库或者静态库,而在动态链接库中还可以再包含其他的动态或静态链接库。
3.动态库就是在需要调用其中的函数时,根据函数映射表找到该函数然后调入堆栈执行。如果在当前工程中有多处对dll文件中同一个函数的调用,那么执行时,这个函数只会留下一份拷贝。但是如果有多处对lib文件中同一个函数的调用,那么执行时,该函数将在当前程序的执行空间里留下多份拷贝,而且是一处调用就产生一份拷贝。
153、在不使用额外空间的情况下,交换两个数?
1.算术
x = x + y;
y = x - y;
x = x - y;
2.异或
x = x^y;// 只能对int,char..
y = x^y;
x = x^y;
x ^= y ^= x;
154、strcpy和memcpy的区别
1、复制的内容不同。strcpy只能复制字符串,而memcpy可以复制任意内容,例如字符数组、整型、结构体、类等。
2、复制的方法不同。strcpy不需要指定长度,它遇到被复制字符的串结束符"\0"才结束,所以容易溢出。memcpy则是根据其第3个参数决定复制的长度。
3、用途不同。通常在复制字符串时用strcpy,而需要复制其他类型数据时则一般用memcpy。
155、简述strcpy、sprintf与memcpy的区别
1.操作对象不同
- strcpy的两个操作对象均为字符串
- sprintf的操作源对象可以是多种数据类型,目的操作对象是字符串
- memcpy的两个对象就是两个任意可操作的内存地址,并不限于何种数据类型。
2.执行效率不同
memcpy最高,strcpy次之,sprintf的效率最低。
3.实现功能不同
- strcpy主要实现字符串变量间的拷贝
- sprintf主要实现其他数据类型格式到字符串的转化
- memcpy主要是内存块间的拷贝。
156、strcpy函数和strncpy函数的区别?哪个函数更安全?
1.函数原型
char* strcpy(char* strDest, const char* strSrc)
char* strncpy(char* strDest, const char* strSrc, int pos)
2.strcpy函数: 如果参数 dest 所指的内存空间不够大,可能会造成缓冲溢出(buffer Overflow)的错误情况,在编写程序时请特别留意,或者用strncpy()来取代。
strncpy函数:用来复制源字符串的前n个字符,src 和 dest 所指的内存区域不能重叠,且 dest 必须有足够的空间放置n个字符。
3.如果目标长>指定长>源长,则将源长全部拷贝到目标长,自动加上’\0’如果指定长<源长,则将源长中按指定长度拷贝到目标字符串,不包括’\0’如果指定长>目标长,运行时错误;
157、执行int main(int argc, char *argv[])时的内存结构
参数的含义是程序在命令行下运行的时候,需要输入argc 个参数,每个参数是以char 类型输入的,依次存在数组里面,数组是 argv[],所有的参数在指针
char * 指向的内存中,数组的中元素的个数为 argc 个,第一个参数为程序的名称(gcc时能够体现)。
158、volatile关键字的作用?
volatile关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改,比如:操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。声明时语法:int volatile vInt;当要求使用 volatile 声明的变量的值的时候,系统总是重新从它所在的内存读取数据,即使它前面的指令刚刚从该处读取过数据。而且读取的数据立刻被保存。
1、性质:
易变性:在汇编层⾯反映出来,就是两条语句,下⼀条语句不会直接使⽤上⼀条语句对应的volatile 变量的寄存器内容,⽽是重新从内存中读取。
不可优化性: volatile 告诉编译器,不要对我这个变量进⾏各种激进的优化,甚⾄将变量直接消除,保证程序员写在代码中的指令,⼀定会被执⾏
顺序性:能够保证 volatile 变量之间的顺序性,编译器不会进⾏乱序优化。
2、应用场景:
1) 中断服务程序中修改的供其它程序检测的变量需要加volatile;
2) 多任务环境下各任务间共享的标志应该加volatile;
3) 存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能由不同意义;
159、讲讲大端小端,如何检测(三种方法)
大端模式:是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址端。
小端模式,是指数据的高字节保存在内存的高地址中,低位字节保存在在内存的低地址端。
1.直接读取存放在内存中的十六进制数值,取低位进行值判断
int a = 0x12345678; int *c = &a; c[0] == 0x12 大端模式 c[0] == 0x78 小段模式
2.用共同体来进行判断
union共同体所有数据成员是共享一段内存的,后写入的成员数据将覆盖之前的成员数据,成员数据都有相同的首地址。Union的大小为最大数据成员的大小。
union的成员数据共用内存,并且首地址都是低地址首字节。int i= 1时:大端存储1放在最高位,小端存储1放在最低位。当读取char ch时,是最低地址首字节,大小端会显示不同的值。
int checkCPUendian()//返回1,为小端;反之,为大端; { union { unsigned int a; unsigned char b; }c; c.a = 1; return 1 == c.b; }
160、查看内存的方法
1.首先打开vs编译器,创建好项目,并且将代码写进去,这里就不贴代码了,你可以随便的写个做个测试;
2.调试的时候做好相应的断点,然后点击开始调试;
2.1程序调试之后会在你设置断点的地方暂停,然后选择调试->窗口->内存,就打开了内存数据查看的窗口了。
目前已整理十万字的C/C++、嵌入式常见面试题!!!!还在持续更新中!!! 这个专栏写完了,再po上自己亲手敲的笔试编程题整理。