嵌入式软件工程师笔试面试指南-CC++

嵌⼊式软件⼯程师笔试⾯试指南-CC++
哈喽,⼤家好。最近⼏天,我把去年秋招总结的笔试⾯试的⼀些内容,⼜进⾏了重新规划分类。详细分成了简历书写,⾯试技巧,⾯经总结,笔试⾯试⼋股⽂总结等四个部分。
其中,⼋股⽂⼜分成了C/C++,数据结构与算法分析,Arm体系与架构,Linux驱动开发,操作系统,⽹络编程,名企笔试真题等七个部分。本次⼋股⽂更新,对于部分不合适的内容进⾏了删减,新增了C++相关内容。
⽂章⽬录
C/C++
关键字
C语⾔宏中"#“和”##"的⽤法
1. (#)字符串化操作符
作⽤:将宏定义中的传⼊参数名转换成⽤⼀对双引号括起来参数名字符串。其只能⽤于有传⼊参数的宏定义中,且必须置于宏定义体中的参数名前。
如:
#define example( instr )printf("the input string is:\t%s\n", #instr )
#define example1( instr )  #instr当使⽤该宏定义时:
example( abc );// 在编译时将会展开成:printf("the input string is:\t%s\n","abc")
string str =example1( abc );// 将会展成:string str="abc"
2. (##)符号连接操作符
作⽤:将宏定义的多个形参转换成⼀个实际参数名。
如:
#define exampleNum( n )  num##n
发光模组
使⽤:
int num9 =9;
ftd vs ks
int num =exampleNum(9);// 将会扩展成 int num = num9
注意:
a. 当⽤##连接形参时,##前后的空格可有可⽆。
如:
#define exampleNum( n )      num ## n
// 相当于 #define exampleNum( n )      num##n
b. 连接后的实际参数名,必须为实际存在的参数名或是编译器已知的宏定义。
c. 如果##后的参数本⾝也是⼀个宏的话,##会阻⽌这个宏的展开。
#include<stdio.h>
#include<string.h>
#define STRCPY(a, b)strcpy(a ## _p, #b)
int main()
{
char var1_p[20];
char var2_p[30];
strcpy(var1_p,"aaaa");
strcpy(var2_p,"bbbb");
STRCPY(var1, var2);
STRCPY(var2, var1);
printf("var1 = %s\n", var1_p);
printf("var2 = %s\n", var2_p);
//STRCPY(STRCPY(var1,var2),var2);
/
/这⾥是否会展开为: strcpy(strcpy(var1_p,"var2")_p,"var2“)?答案是否定的:
//展开结果将是:  strcpy(STRCPY(var1,var2)_p,"var2")
//## 阻⽌了参数的宏展开!如果宏定义⾥没有⽤到 # 和 ##, 宏将会完全展开
// 把注释打开的话,会报错:implicit declaration of function 'STRCPY'
return0;
}
结果:
var1 = var2
var2 = var1
关键字volatile有什么含意?并举出三个不同的例⼦?
1. 并⾏设备的硬件寄存器。存储器映射的硬件寄存器通常加volatile,因为寄存器随时可以被外设硬件修改。当声明指向设备寄存器的指
针时⼀定要⽤volatile,它会告诉编译器不要对存储在这个地址的数据进⾏假设。
2. ⼀个中断服务程序中修改的供其他程序检测的变量。volatile提醒编译器,它后⾯所定义的变量随时都有可能改变。因此编译后的程序
每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据。如果没有volatile关键字,则编译器可能优化读取和存储,可能暂时使⽤寄存器中的值,如果这个变量由别的程序更新了的话,将出现不⼀致的现象。
3. 多线程应⽤中被⼏个任务共享的变量。单地说就是防⽌编译器对代码进⾏优化.⽐如如下程序:
XBYTE[2]=0x55;
XBYTE[2]=0x56;
XBYTE[2]=0x57;
XBYTE[2]=0x58;
对外部硬件⽽⾔,上述四条语句分别表⽰不同的操作,会产⽣四种不同的动作,但是编译器却会对上
述四条语句进⾏优化,认为只有XBYTE[2]=0x58(即忽略前三条语句,只产⽣⼀条机器代码)。如果键⼊volatile,编译器会逐⼀的进⾏编译并产⽣相应的机器代码(产⽣四条代码)。
关键字static的作⽤是什么?
1. 在函数体,只会被初始化⼀次,⼀个被声明为静态的变量在这⼀函数被调⽤过程中维持其值不变。
2. 在模块内(但在函数体外),⼀个被声明为静态的变量可以被模块内所⽤函数访问,但不能被模块外其它函数访问。它是⼀个本地的
全局变量(只能被当前⽂件使⽤)。
3. 在模块内,⼀个被声明为静态的函数只可被这⼀模块内的其它函数调⽤。那就是,这个函数被限制在声明它的模块的本地范围内使⽤
(只能被当前⽂件使⽤)。
在C语⾔中,为什么 static变量只初始化⼀次?
对于所有的对象(不仅仅是静态对象),初始化都只有⼀次,⽽由于静态变量具有“记忆”功能,初始
化后,⼀直都没有被销毁,都会保存在内存区域中,所以不会再次初始化。存放在静态区的变量的⽣命周期⼀般⽐较长,它与整个程序“同⽣死、共存亡”,所以它只需初始化⼀次。⽽auto变量,即⾃动变量,由于它存放在栈区,⼀旦函数调⽤结束,就会⽴刻被销毁。
extern”C” 的作⽤是什么?
extern "C"的主要作⽤就是为了能够正确实现C++代码调⽤其他C语⾔代码。加上extern "C"后,会指⽰编译器这部分代码按C语⾔的进⾏编译,⽽不是C++的。
const有什么作⽤?
1. 定义变量(局部变量或全局变量)为常量,例如:
const int N=100;//定义⼀个常量N
N=50;//错误,常量的值不能被修改
const int n;//错误,常量在定义的时候必须初始化
2. 修饰函数的参数,表⽰在函数体内不能修改这个参数的值。
3. 修饰函数的返回值。
a.如果给⽤ const修饰返回值的类型为指针,那么函数返回值(即指针)的内容是不能被修改的,⽽且这个返回值只能赋给被 const
修饰的指针。例如:
const char GetString()//定义⼀个函数
char*str=GetString()//错误,因为str没有被 const修饰
const char*str=GetString()//正确
水性万能胶
b.如果⽤ const修饰普通的返回值,如返回int变量,由于这个返回值是⼀个临时变量,在函数调⽤结束后这个临时变量的⽣命周期也
就结束了,因此把这些返回值修饰为 const是没有意义的。
4. 节省空间,避免不必要的内存分配。例如:
药盒#define PI 3.14159//该宏⽤来定义常量
const doulbe Pi=3.14159//此时并未将P放⼊只读存储器中
double i=Pi//此时为Pi分配内存,以后不再分配
double I=PI//编译期间进⾏宏替换,分配内存
double j=Pi//没有内存分配再次进⾏宏替换,⼜⼀次分配内存
什么情况下使⽤const关键字?
1. 修饰⼀般常量。⼀般常量是指简单类型的常量。这种常量在定义时,修饰符const可以⽤在类型说明符前,也可以⽤在类型说明符后。
例如:
int const x=2;const int x=2
2. 修饰常数组。定义或说明⼀个常数组可以采⽤如下格式:
int const a[8]={1,2,3,4,5,6,7,8}磁力搅拌罐
const int a[8]={1,2,3,4,5,6,7,8}
3. 修饰常对象。常对象是指对象常量,定义格式如下:
class A:
const A a:
A const a:
定义常对象时,同样要进⾏初始化,并且该对象不能再被更新。修饰符 const可以放在类名后⾯,也可以放在类名前⾯。
4. 修饰常指针
const int*p;//常量指针,指向常量的指针。即p指向的内存可以变,p指向的数值内容不可变
int const*p;//同上
int*const p;//指针常量,本质是⼀个常量,⽽⽤指针修饰它。即p指向的内存不可以变,但是p内存位置的数值可以变
const int*const p;//指向常量的常量指针。即p指向的内存和数值都不可变
5. 修饰常引⽤。被 const修饰的引⽤变量为常引⽤,⼀旦被初始化,就不能再指向其他对象了。
6. 修饰函数的常参数。 const修饰符也可以修饰函数的传递参数,格式如下:
void Fun(const int Var)
  告诉编译器Var在函数体中不能被改变,从⽽防⽌了使⽤者⼀些⽆意的或错误的修改。
7. 修饰函数的返回值。 const修饰符也可以修饰函数的返回值,表明该返回值不可被改变,格式如下:
const int FunI();
const MyClass Fun2();
8. 在另⼀连接⽂件中引⽤ const常量。使⽤⽅式有
extern const int1:
extern const int j=10;
new/delete与malloc/free的区别是什么?
1. new、delete是C++中的操作符,⽽malloc和free是标准库函数。
2. 对于⾮内部数据对象来说,只使⽤malloc是⽆法完成动态对象要求的,⼀般在创建对象时需要调⽤构造函数,对象消亡时,⾃动的调
⽤析构函数。⽽malloc free是库函数⽽不是运算符,不在编译器控制范围之内,不能够⾃动调⽤构造函数和析构函数。⽽NEW在为对象申请分配内存空间时,可以⾃动调⽤构造函数,同时也可以完成对对象的初始化。同理,delete也可以⾃动调⽤析构函数。⽽mallloc只是做⼀件事,只是为变量分配了内存,同理,free也只是释放变量的内存。
3. new返回的是指定类型的指针,并且可以⾃动计算所申请内存的⼤⼩。⽽ malloc需要我们计算申请内存的⼤⼩,并且在返回时强⾏转
换为实际类型的指针。
strlen("\0") =? sizeof("\0")=?
strlen("\0") =0,sizeof("\0")=2。
strlen⽤来计算字符串的长度(在C/C++中,字符串是以"\0"作为结束符的),它从内存的某个位置(
可以是字符串开头,中间某个位置,甚⾄是某个不确定的内存区域)开始扫描直到碰到第⼀个字符串结束符\0为⽌,然后返回计数器值sizeof是C语⾔的关键字,它以字节的形式给出了其操作数的存储⼤⼩,操作数可以是⼀个表达式或括在括号内的类型名,操作数的存储⼤⼩由操作数的类型决定。
sizeof和strlen有什么区别?
strlen与 sizeof的差别表现在以下5个⽅⾯。
1. sizeof是运算符(是不是被弄糊涂了?事实上, sizeof既是关键字,也是运算符,但不是函数),⽽strlen是函数。 sizeof后如果是
类型,则必须加括弧,如果是变量名,则可以不加括弧。
2. sizeof运算符的结果类型是 size_t,它在头⽂件中 typedef为 unsigned int类型。该类型保证能够容纳实现所建⽴的最⼤对象的字节
⼤⼩
3. sizeof可以⽤类型作为参数, strlen只能⽤char*作参数,⽽且必须是以“0结尾的。 sizeof还可以以函数作为参数,如int g(),则
sizeof(g())的值等于 sizeof( int的值,在32位计算机下,该值为4。
4. ⼤部分编译程序的 sizeof都是在编译的时候计算的,所以可以通过 sizeof(x)来定义数组维数。⽽ strlen则是在运⾏期计算的,⽤
来计算字符串的实际长度,不是类型占内存的⼤⼩。例如, char str[20] = "0123456789”,字符数组str是编译期⼤⼩已经固定的数组,在32位机器下,为 sizeof(char)*20=20,⽽其 strlen⼤⼩则是在运⾏期确定的,所以其值为字符串的实际长度10。
5. 当数组作为参数传给函数时,传递的是指针,⽽不是数组,即传递的是数组的⾸地址。
不使⽤ sizeof,如何求int占⽤的字节数?
#include<stdio.h>
#define MySizeof(Value)(char*)(&value+1)-(char*)&value
int main()
{
int i ;
double f;
double*q;
分离式行车记录仪printf("%d\r\n",MySizeof(i));
printf("%d\r\n",MySizeof(f));
printf("%d\r\n",MySizeof(a));
printf("%d\r\n",MySizeof(q));
return0;
}
输出为:
4 8 32 4
上例中,(char*)& Value返回 Value的地址的第⼀个字节,(char*)(& Value+1)返回value的地址的下⼀个地址的第⼀个字节,所以它们之差为它所占的字节数。
C语⾔中 struct与 union的区别是什么?
struct(结构体)与 union(联合体)是C语⾔中两种不同的数据结构,两者都是常见的复合结构,其区别主要表现在以下两个⽅⾯。
1. 结构体与联合体虽然都是由多个不同的数据类型成员组成的,但不同之处在于联合体中所有成员共⽤⼀块地址空间,即联合体只存放
了⼀个被选中的成员,⽽结构体中所有成员占⽤空间是累加的,其所有成员都存在,不同成员会存放在不同的地址。在计算⼀个结构型变量的总长度时,其内存空间⼤⼩等于所有成员长度之和(需要考虑字节对齐),⽽在联合体中,所有成员不能同时占⽤内存空间,它们不能同时存在,所以⼀个联合型变量的长度等于其最长的成员的长度。
2. 对于联合体的不同成员赋值,将会对它的其他成员重写,原来成员的值就不存在了,⽽对结构体的不同成员赋值是互不影响的。
举个例⼦。下列代码执⾏结果是多少?
typedef union{double i;int k[5];char c;}DATE;
typedef struct data(int cat; DATE cow;double dog;)too;
DATE max;
printf("%d",sizeof(too)+sizeof(max));
假设为32位机器,int型占4个字节, double型占8个字节,char型占1个字节,⽽DATE是⼀个联合型变量,联合型变量共⽤空间,uion ⾥⾯最⼤的变量类型是int[5],所以占⽤20个字节,它的⼤⼩是20,⽽由于 union中 double占了8个字节,因此 union是要8个字节对齐,所占内存空间为8的倍数。为了实现8个字节对齐,所占空间为24.⽽data是⼀个结构体变量,每个变量分开占⽤空间,依次为
sizeof(int)+ sizeof(DATE)+ sizeof( double)=4+24+8=36按照8字节对齐,占⽤空间为40,所以结果为40+24=64。

本文发布于:2024-09-25 10:28:48,感谢您对本站的认可!

本文链接:https://www.17tex.com/tex/2/280914.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:变量   函数   参数
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议