嵌软八股大全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相关问题汇总,希望能帮助求职者了解考试趋势和嵌入式常见考点。无论你是准备面试,还是希望提升自己的专业知识,这里都能为你提供宝贵的参考和学习资源。

全部评论

相关推荐

评论
点赞
2
分享

创作者周榜

更多
牛客网
牛客企业服务