嵌软八股大全2 - C & C++ 相关问题汇总
Basic
1、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 |
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 表
重点记忆以下几个:
10 | LF | 换行 |
13 | CR | 回车 |
32 | (space) | 空格 |
48 | 0 | |
65 | A | |
97 | a |
7、进制
C/C++ 中都有哪些进制?
- 二进制
- 八进制,前缀
0
- 十进制
- 十六进制,前缀
0x
或0X
C 中不能用来表示整常数的进制?
十进制、八进制、十六进制都可以用来表示整常数,二进制不可以
8、什么是大小端?
大端序(Big Endian) -> 高位字节存储在低地址,低位字节存储在高地址 -> 高低低高
小端序(Little Endian) -> 低位字节存储在低地址,高位字节存储在高地址 -> 低低高高
9、C++ 组成部分
标准的 C++ 由三个重要部分组成:
- 核心语言
- C++ 标准库
- 标准模板库(STL)
10、UML?
UML(Unified Modeling Language,统一建模语言)提供了一系列图表,用于在软件工程中描述和设计系统的结构和行为,主要有如下几种类型
- 结构图
- 类图
- 对象图
- 组件图
- 部署图
- 行为图
- 用例图
- 活动图
- 状态机图
- 序列图
11、设计模式?
设计模式分为创建型模式、结构型模式 和 行为型模式三大类,具体如下所示
- 创建型模式
- 单例模式(Singleton):一个类只有一个实例,并提供一个全局访问点
- 工厂方法模式(Factory Method):定义一个创建对象的接口,让子类决定实例化哪一个类
- ...
- 结构型模式 4. 装饰器模式(Decorator):定义对象间的一对多依赖关系,当一个对象状态发生改变时,所有依赖的对象都会自动收到通知并更新 5. ...
- 行为型模式
- 策略模式:定义一系列算法,并将每个算法封装起来,使得它们可以互换使用
- 观察者模式:动态地给对象添加额外的职责,而不改变其结构
- ...
在 C++ 中如何实现上述设计模式?
- 单例模式:通过将构造函数私有化来实现
- 工厂方法模式:通过基类中定义纯虚函数变为抽象类来实现
- ...
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
具体步骤如下所示
- 预处理(主要处理
#
开头的语句)- 宏定义字符串替换
- 头文件包括
- 条件编译
- 删除注释和多余的空白
- 编译
- 语法分析(检查代码的语法和结构是否正确),语义分析(检查类型和操作是否合法)
- 生成中间代码,进行初步优化
- 源文件 -> 汇编代码
- 汇编
- 汇编指令 -> 机器码
- 链接
- 将多个目标文件合并,解决外部符号和引用
- 将库文件(静态库或动态库)与目标文件链接
- 分配内存地址和解决所有符号引用
2、指针 VS 引用?
指针(C/C++中均存在)
- 指针是指向另一个对象的变量,指针保存的是另一个对象的地址
- 指针指向的值可以被修改
- 指针可以在任何时间被初始化
引用(只有C++中存在)
- 引用是某个已存在变量的别名
- 引用一旦初始化便不可修改
- 引用只能在定义时被初始化
- 不存在空引用
指针作为函数参数/返回值(传递的是指针副本)的优缺点
- 优点
- 灵活性高
- 动态内存管理
- 缺点
- 易出错
- 安全性低
// 使用指针交换两个值
void ptr_swap(int *a, int *b)
{
int temp;
temp = *a;
*a = *b;
*b = temp;
}
引用作为函数参数/返回值(传递的是引用对象别名)的优缺点
- 优点
- 简单易用
- 安全性高
- 高效,避免了值传递的开销
- 缺点
- 灵活性低
- 不能引用数组
- 不能重新绑定
// 使用引用交换两个值
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 数组?
- 链表和数组都是常见的线性数据结构
- 链表中各个链表项在内存中是不连续的,数组中各个元素在内存中是连续的
- 链表定义好之后长度还可以变化,数组一旦定义好长度就不能变化
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(){} // 方法
};
三者区别汇总
内存分配 | 与结构体类似 | 成员间内存独立 | 成员共享同一内存 |
默认访问控制 | private | public | public |
用途 | 面向对象,定义对象及行为 | 描述复杂的数据结构 | 节约内存 |
语言支持 | C++ | C/C++ | C/C++ |
5、define
VS typedef
?
define
是预处理指令,而 typedef
是 C/C++ 的关键字
define
只做简单的字符串替换,而 typedef
会进行类型的检查
类型不同 | 预处理指令 | 关键字 | 关键字 |
类型检查 | 无,简单字符串替换 | 有 | - |
生效阶段 | 预处理阶段 | 编译阶段 | 编译阶段 |
功能不同 | 别名、常量、编译开关等 | 只读 |
6、sizeof
VS strlen
?
- sizeof(),单目运算符,以字节形式给出其操作数的存储大小,编译时计算
- srelen(),库函数,计算字符串的长度(不算结束字符 ’\0‘ ),运算时计算
strlen(“\\0” )
VS sizeof(“\\0”
?
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
欢迎来到我的专栏,在这里,我将整理并分享2024年各大企业的真实笔试/面试真题,同时还整理了嵌入式软件相关的八股知识。专栏内容涵盖C/C++基础、嵌软常见通信协议、ARM、FreeRTOS、Linux OS相关问题汇总,希望能帮助求职者了解考试趋势和嵌入式常见考点。无论你是准备面试,还是希望提升自己的专业知识,这里都能为你提供宝贵的参考和学习资源。