嵌软八股大全2 - C & C++ 相关问题汇总

Basic

1、C & C++ 标准

年份 C 标准 名称
1972 --- C 诞生
1978 --- “K&R” C
1989 ANSI X3.159-1989 ANSI C(C89)
1990 ISO/IEC 9899:1990 C90
1999 ISO/IEC 9899:1999 C99
2011 ISO/IEC 9899:2011 C11
2018 ISO/IEC 9899:2018 C17/C18
2023 ISO/IEC 9899:2023 C23
年份 C++ 标准 名称
1979 --- C with Classes 诞生
1983 --- 正式命名 C++
1998 ISO/IEC 14882:1998 C++98
2003 ISO/IEC 14882:2003 C++03
2011 ISO/IEC 14882:2011 C++11
2014 ISO/IEC 14882:2014 C++14
2017 ISO/IEC 14882:2017 C++17
2020 ISO/IEC 14882:2020 C++20
2023 ISO/IEC 14882:2020 C++23

2、运算符 operator

2.1、运算符种类

种类 运算符 功能 用法
算数运算符
+ 加/正
- 减/负
*
/
% 取余 整数 % 整数
自增/自减运算符
++ 自加
-- 自减
关系运算符
** 等于
!= 不等于
> 大于
< 小于
>= 大于等于
<= 小于等于
逻辑运算符
&& 逻辑与
|| 逻辑或
! 逻辑非
位运算符
& 按位与
| 按位或
^ 按位异或
~ 按位取反
>> 右移
<< 左移
赋值运算符
= 赋值 a=b
+= 加且赋值 a+=b
a=a+b
-= 减且赋值 a-=b
a=a-b
*= 乘且赋值
/= 除且赋值
%= 取余且赋值
<<= 左移且赋值
>>= 右移且赋值
&= 按位与且赋值
|= 按位或且赋值
^= 按位异或且赋值
杂项运算符
& 取地址 &a 表示获取变量 a 在内存中的地址
* 获取指针指向地址的值
?: 条件表达式 x>y?x:y

2.2、运算符优先级

优先级 运算符 描述 结合性
1 ++
--
()
[]
.
->
(_type_){_list_}
后缀自增
后缀自减
函数调用
数组下标
从左到右
2 ++
--
+
-
!
~
(_type_)
*
&
sizeof
_Alignof
前缀自增
前缀自减





间接(解引用)
取址

从右到左
3 *
/
%
乘法
除法
取余
从左到右
4 +
-
加法
减法
5 <<
>>
6 <
<=
>
>=
7 **
!=
8 &
9 ^
10 |
11 &&
12 ||
13 ?: 三元条件 从右到左
14 =
+=
-=
*=
/=
%=
<<=
>>=
&=
^=
|=
赋值
15 , 逗号 从左到右

3、原码、反码、补码

正数的原码 = 其反码 = 其补码

十进制:10
原码:0000 1010
反码:0000 1010
补码:0000 1010

负数的反码 = 其原码按位取反 (符号位不变)

负数的补码 = 其反码 + 1

十进制:-10
原码:1000 1010,最高位为符号位 1
反码:1111 0101,原码按位取反,符号位不变
补码:1111 0110,反码+1

4、短路求值

使用 &&|| 运算符运算时,左边第一项不满足/满足时直接返回,不会再对运算符右边运算

#include "stdio.h"  
  
int main(void)  
{  
    int a = 3, b =4;
    //对于与运算,左边第一项不满足,直接返回,不会对右边式子运算 
    !a && (b++);  
    //对于或运算,左边第一项满足,直接返回,不会对右边式子运算 
	a || (b--);

    printf("a=%d,b=%d\n", a, b);  
    return 0;  
}
output:
	a=3,b=4

5、隐式类型转换

不同类型进行运算时,没指出转换的类型时,它会往容量大的类型转换,这样容易避免溢出

6、ASCII 表

重点记忆以下几个:

ASCII 控制字符 含义
10 LF 换行
13 CR 回车
32 (space) 空格
48 0
65 A
97 a

7、进制

C/C++ 中都有哪些进制?

  1. 二进制
  2. 八进制,前缀 0
  3. 十进制
  4. 十六进制,前缀 0x0X

C 中不能用来表示整常数的进制?

十进制、八进制、十六进制都可以用来表示整常数,二进制不可以

8、什么是大小端?

大端序(Big Endian) -> 高位字节存储在低地址,低位字节存储在高地址 -> 高低低高

小端序(Little Endian) -> 低位字节存储在低地址,高位字节存储在高地址 -> 低低高高

9、C++ 组成部分

标准的 C++ 由三个重要部分组成:

  1. 核心语言
  2. C++ 标准库
  3. 标准模板库(STL)

10、UML?

UML(Unified Modeling Language,统一建模语言)提供了一系列图表,用于在软件工程中描述和设计系统的结构和行为,主要有如下几种类型

  1. 结构图
    1. 类图
    2. 对象图
    3. 组件图
    4. 部署图
  2. 行为图
    1. 用例图
    2. 活动图
    3. 状态机图
    4. 序列图

11、设计模式?

设计模式分为创建型模式、结构型模式 和 行为型模式三大类,具体如下所示

  1. 创建型模式
    1. 单例模式(Singleton):一个类只有一个实例,并提供一个全局访问点
    2. 工厂方法模式(Factory Method):定义一个创建对象的接口,让子类决定实例化哪一个类
    3. ...
  2. 结构型模式 4. 装饰器模式(Decorator):定义对象间的一对多依赖关系,当一个对象状态发生改变时,所有依赖的对象都会自动收到通知并更新 5. ...
  3. 行为型模式
    1. 策略模式:定义一系列算法,并将每个算法封装起来,使得它们可以互换使用
    2. 观察者模式:动态地给对象添加额外的职责,而不改变其结构
    3. ...

在 C++ 中如何实现上述设计模式?

  1. 单例模式:通过将构造函数私有化来实现
  2. 工厂方法模式:通过基类中定义纯虚函数变为抽象类来实现
  3. ...

C

1、C/C++ 程序编译过程?

问题别名:gcc 编译过程?

预处理(Pre-Processing) -> 编译(Compilation) -> 汇编(Assembling) -> 链接(Linking)

# 预处理
gcc -E hello.c -o hello.i
# 编译
gcc -S hello.i -o hello.s
# 汇编
gcc -c hello.s -o hello.o
# 链接
gcc hello.o -o hello

alt

具体步骤如下所示

  1. 预处理(主要处理 # 开头的语句)
    1. 宏定义字符串替换
    2. 头文件包括
    3. 条件编译
    4. 删除注释和多余的空白
  2. 编译
    1. 语法分析(检查代码的语法和结构是否正确),语义分析(检查类型和操作是否合法)
    2. 生成中间代码,进行初步优化
    3. 源文件 -> 汇编代码
  3. 汇编
    1. 汇编指令 -> 机器码
  4. 链接
    1. 将多个目标文件合并,解决外部符号和引用
    2. 将库文件(静态库或动态库)与目标文件链接
    3. 分配内存地址和解决所有符号引用

2、指针 VS 引用?

指针(C/C++中均存在)

  1. 指针是指向另一个对象的变量,指针保存的是另一个对象的地址
  2. 指针指向的值可以被修改
  3. 指针可以在任何时间被初始化

引用(只有C++中存在)

  1. 引用是某个已存在变量的别名
  2. 引用一旦初始化便不可修改
  3. 引用只能在定义时被初始化
  4. 不存在空引用

指针作为函数参数/返回值(传递的是指针副本)的优缺点

  1. 优点
    1. 灵活性高
    2. 动态内存管理
  2. 缺点
    1. 易出错
    2. 安全性低
// 使用指针交换两个值
void ptr_swap(int *a, int *b)  
{  
    int temp;  
    temp = *a;  
    *a = *b;  
    *b = temp;  
}

引用作为函数参数/返回值(传递的是引用对象别名)的优缺点

  1. 优点
    1. 简单易用
    2. 安全性高
    3. 高效,避免了值传递的开销
  2. 缺点
    1. 灵活性低
    2. 不能引用数组
    3. 不能重新绑定
// 使用引用交换两个值
void ref_swap(int &a, int &b)  
{  
  int temp;  
  temp = a;  
  a = b;  
  b = temp;  
}

区别汇总

指针 引用
定义形式 int x;
int *ptr=&x;
int x;
int &ref=x;
为空情况 ptr=NULL; 引用不可为空
内存地址 指针保存着指向变量的地址,同时指针也有自己的内存地址 引用是原变量的别名,无自己的内存地址
赋值情况 指针可以重新赋值为其他地址 引用一旦绑定了某个对象便不可修改
空间占用 指针需存储指向变量地址,需要占用内存 引用只是别名,不占用空间
算数运算 指针可进行算术运算、递增、递减等操作 引用不能进行算术运算、递增、递减等操作

3、链表 VS 数组?

  1. 链表和数组都是常见的线性数据结构
  2. 链表中各个链表项在内存中是不连续的,数组中各个元素在内存中是连续的
  3. 链表定义好之后长度还可以变化,数组一旦定义好长度就不能变化

4、联合体 VS 结构体 VS 类?

union 是联合体/共用体,允许在相同的内存位置存储不同的数据类型,大小等于其最大成员的大小
struct 是结构体,允许存储不同类型的数据项,大小等于所有成员大小的总和 + 填充字节
class 是 C++ 中的类,面向对象核心概念,具有访问控制,可继承,有多态概念

以下是其定义方法

// 联合体
// 关键词 标签
union union_tag  
{  
  int member1;  
  ...  
}union_var;  

// 结构体
struct struct_tag  
{  
  int member1;  
  ...  
}struct_var;

// 类
class classname  
{  
public:                       // 访问修饰符,public、private、protected
  Datemembers variables;      // 变量  
  Memberfunctions(){}         // 方法  
};

三者区别汇总

class struct union
内存分配 与结构体类似 成员间内存独立 成员共享同一内存
默认访问控制 private public public
用途 面向对象,定义对象及行为 描述复杂的数据结构 节约内存
语言支持 C++ C/C++ C/C++

5、define VS typedef

define 是预处理指令,而 typedef 是 C/C++ 的关键字
define 只做简单的字符串替换,而 typedef 会进行类型的检查

define typedef const
类型不同 预处理指令 关键字 关键字
类型检查 无,简单字符串替换 -
生效阶段 预处理阶段 编译阶段 编译阶段
功能不同 别名、常量、编译开关等 只读

6、sizeof VS strlen

  1. sizeof(),单目运算符,以字节形式给出其操作数的存储大小,编译时计算
  2. srelen(),库函数,计算字符串的长度(不算结束字符 ’\0‘ ),运算时计算

strlen(“\\0” ) VS sizeof(“\\0” ?

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

欢迎来到我的专栏,在这里,我将整理并分享2024年各大企业的真实笔试/面试真题,同时还整理了嵌入式软件相关的八股知识。专栏内容涵盖C/C++基础、嵌软常见通信协议、ARM、FreeRTOS、Linux OS相关问题汇总,希望能帮助求职者了解考试趋势和嵌入式常见考点。无论你是准备面试,还是希望提升自己的专业知识,这里都能为你提供宝贵的参考和学习资源。

全部评论

相关推荐

“金三银四”的招聘季,本该是打工人收割Offer的黄金时刻,你却像个孤勇者在求职战场疯狂输出:第100份简历投出,依然0面试邀约,连HR的「已读不回」都成了奢侈品;明明手握大厂项目经验,简历却写得像岗位说明书,HR扫5秒就划走;熬夜改了三版「全网爆款模板」,却在AI初筛环节被判定为「关键词匹配度不足」‍今天就用一篇实操攻略,教你如何用DeepSeek写出完美简历,仅需3句指令。【第一步「拆解JD」】先让deepseek根据JD帮你总结目标岗位要求。首先你需要去各大招聘网站上找到三份你要应聘的岗位JD作为参考,尽量用大厂JD,岗位职责描述更精准。指令如下:我想要应聘XX岗位。请结合以下三份JD,帮我总结出这个岗位需要的技能和工作要求。‍以「用户增长运营」为例,把找到的3个岗位JD复制粘贴到指令下方,如图1。仅需5s,你将得到一份招聘市场上该岗位通用的人才标准,如图2。【第二步出模版】让deepseek结合你的基本信息和刚刚总结出来的标准岗位要求,出一份简历模版。指令如下:我是应届生/社招,毕业于XX大学。实习经历:xxx,校园经历:xxx。请结合SWOT分析法帮我写一份与这三份JD相匹配的简历,包括以下部分:个人优势,教育经历,实习经历,校园经历,技能证书。‍几秒钟生成一份符合你经历又契合岗位JD的简历,个人优势、项目描述,还有数据支撑,如图三。还帮你优化了项目经历,比如把简历侧重点放在突出“AI+媒体”的背景,而且把所有的经历都进行了数据绑定,展示可量化的成果。【第三步是优化模版‍】为了让简历更有针对性,我们要根据目标公司的发展重点,让deepseek优化对应模块。指令如下:目标公司侧重XX,帮我优化对应模块,增加一些项目经历,如图四。根据你的要求会为你增加更多的项目颗粒度,让你的简历更加贴合目标单位的招聘标准。当然~这只是个模板,记得还是要根据自己的真实项目信息、数据去修改细节。💡最后,如果你担心用这份简历会被HR问崩的话,可以试试用「面试大师」进行面试前的模拟提问,使用方法如下:1⃣️在面试大师官网(mianshidashi.cn)上传简历2⃣️点击「模拟面试」页面的「开始面试」3⃣️此时AI会根据你的简历生成面试题,供你在正式面试前进行模拟训练⚠️你也可以在正式面试时把「面试大师」当面试提词器来用,只需在上传简历后点击「AI面试」,然后点击开始面试即可~可以选择符合自己需求的面试模式(不同模式的适用场景可在官网看到),补充信息可以填写岗位JD和面试公司的详细信息。进入面试页面即可正常时使用(记得共享系统音频)。此时面试官提问,ai便会语音识别问题,并迅速给出符合你工作经历的答案~#简历中的项目经历要怎么写##你见过最离谱的招聘要求是什么?##牛客创作赏金赛##春招#
点赞 评论 收藏
分享
03-22 11:53
已编辑
门头沟学院 C++
1.&nbsp;被free回收的内存是立即返回给操作系统吗?2.&nbsp;sizeof和strlen的区别?3.&nbsp;new/delete、malloc/free的区别4.&nbsp;堆快一点还是栈快一点?5.&nbsp;在main执行之前和执行之后执行的代码可能是什么?6.&nbsp;final和override的关键字?7.&nbsp;拷贝初始化和直接初始化?8.&nbsp;select、poll、epoll9.Reactor?10.&nbsp;阻塞、非阻塞、同步、异步?11.&nbsp;Proactor?1.&nbsp;被free回收的内存首先会被ptmalloc使用双链表保存起来,当有用户申请内存的时候,会直接从这里面找出合适的内存进行返回。这样可以避免操作系统的频繁调用,另外它还会将小内存进行合并,防止产生过多的内存碎片;2.&nbsp;sizeof是运算符,strlen是库函数。sizeof的参数可以是任何数据的类型或数据,strlen的参数只能是字符串的指针,且结束符为&#39;\0&#39;的字符;3.&nbsp;前者是C++运算符,后者是C/C++库函数;new自动计算要分配的内存对象,malloc需要计算;new是类型安全的,malloc不是;调用new的给自定义对象分配内存的时候,会调用构造函数并分配相应的内存,delete的时候会释放内存并执行析构;4.&nbsp;&nbsp;栈快一点,操作系统堆栈提供支持,有分配专门的寄存器存放栈的地址,栈的出入栈也十分简单,并且有专门的指令执行,所以栈的效率更高更快;而堆在分配的内存的时候要使用算法寻找合适大小的内存,并且在获取堆的内容的时候需要两次访问,一次指针,一直是指针保存的地址5.&nbsp;初始化全局变量和静态变量,即.data段数据,将未初始化的全局变量进行赋值;全局对象初始化;将argc、argv传递给main函数;___attribute___(constructor);结束后,全局的析构函数会在main函数执行完后析构,可用一个atexit注册一个函数会在main函数之后执行;___attribute___(destructor)6.&nbsp;override的关键字,指定了子类的这个虚函数必须重写父类的,如果函数名不小心打错了,编译器会进行报错,不会通过;当不希望某个类被继承、或不希望虚函数被重写可以在类名和虚函数后面添加final关键字;7.&nbsp;直接初始化直接调用与实参匹配的构造函数;拷贝初始化首先使用指定构造函数创建一个临时对象,然后用拷贝构造函数将那个零食对象拷贝到正在创建的对象;8.&nbsp;select函数将已连接的socket都放到一个文件描述符集合,然后调用select函数将文件描述符拷贝到内核中,去遍历进行检测那个套接字发生事件,将其进行标记,后续再复制到用户态,进行遍历找到标记的套接字。这其中发生了2次遍历文件描述符集合和2次拷贝文件描述符集合。poll突破文件描述符个数的限制(1024),通过一个动态数组,以链表的形式管理。其它与select还是一样的。epoll通过在内核中使用红黑树来跟踪进程所有待检测的文件描述符,把需要监控的socket通过epoll_ctl函数加入到内核中的红黑树,第二,epoll使用时间驱动的机制,内核里维护了一个链表来记录就绪事件,当某个socket事件发生时,通过回调函数内核将其加入到就绪事件列表中,当用户调用epoll_wait函数时,只会返回有事件发生的文件描述符的个数。9.&nbsp;reactor模型是&nbsp;I/O&nbsp;多路复用监听事件,收到事件后,根据事件类型分配(Dispatch)给某个进程&nbsp;/&nbsp;线程。单reactor单进程:reactor对象通过epoll监听事件,收到事件后通过dispatch进行分发,如果是连接建立的事件交个Acceptor对象进行处理,如果不是就交给Handle对象通过read-&gt;业务处理-&gt;send的流程来完成完整的业务流程。单reactor多线程:对于不是连接建立事件,则交由Handler对象处理,他不负责业务处理,只负责数据的接受和发送,数据会发送给线程池来进行业务处理,处理完成后将业务结果返回给handler对象,然后发送给client;多reactor多线程:主线程只负责接受新连接,子线程负责完成后续的业务处理。主线程只需要把新连接传给子线程,子线程进行业务处理后,直接可以将处理结果发送给客户端。10.&nbsp;阻塞I/O:当用户执行read,线程会被阻塞,一直等到内核数据准备好[1],并把数据从内核缓冲区拷贝到应用缓冲区中[2],当拷贝完成,read才返回。非阻塞I/O:可以在数据未准备好久立即返回,然后应用程序不断轮训内核,直到数据准备好,[2]操作还是要的;异步I/O:上面的[1]和[2]的步骤都不需要等待,都交由内核完成。11.&nbsp;Reactor模式是基于待完成的I/O事件,而Proactor模式是基于[已完成]的I/O事件。
点赞 评论 收藏
分享
评论
点赞
2
分享

创作者周榜

更多
牛客网
牛客企业服务