收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。
需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人
都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
还是唐老师的视频,还是老样子,既然看了学了,就做点笔记做点精简和总结,
以后有用得到的地方,也方便查找。本文章只有比较C与C++ 有联系的不同之处,并没有C++独有的内容。
..添加目录栏目 2021/9/17
目录
1、C到C++的升级
变量定义
- 所有的变量都可以在需要使用时再定义
int c = 0;
for(int i=1; i<=3; i++)
{
for(int j=1; j<=3; j++)
{
c += i \* j;
}
}
- register 关键字请求编译器将局部变量存储于寄存器中,C++ 依然支持,有自己的优化方式,C++ 中可以取得 register 变量的地址,如果有对变量取地址的操作,register 会直接忽略。 register 基本上使用中看不到,但是为了兼容C语言,鸡肋,形同虚设,不用!!!
- 在C语言中,可以重复定义多个同名的全局变量, 在C++中,不允许定义多个同名的全局变量
C语言中多个同名的全局变量最终会被连接到全局数据区的同一个地址空间上,C++直接拒绝这种二义性的做法
struct关键字的加强
- C语言中的struct定义了 一组变量的集合
- C语言中struct 定义的 标识符 并不 是一种新的类型
- C++ 中的 struct用于定义一个全新的类型
int f() 和 int f(void)
- C++中所有的 标识符都必须显示的声明类型
- C语言中的 默认类型 在C++ 中是不合法的
布尔类型
bool 是C++ 中的基本数据类型,可以定义bool类型的 全局变量,常量,指针,数组
三目运算符
C++对三目运算符做了什么?
- 当三目运算符的 可能返回都是变量时,返回的是变量引用(引用的解释见第 3 大点,3、引用部分)
- 当三目运算符的 可能返回中有常量时,返回的是值
2、进化后const的分析
C与C++中const的比较
在C语言中:
int main()
{
const int c = 0;
int\* p = (int\*)&c;
\*p = 5;
printf("c = %d\n", c);//c语言中可以改变 c= 5,C++中 c= 0
printf("\*p = %d\n", \*p);
printf("End...\n");
return 0;
}
void f()
{
#define a 3
const int b = 4;
}
void g()
{
printf("a = %d\n", a); //C++编译不会报错,这个地方编译器看到的a 是3
printf("b = %d\n", b); //C++编译报错,编译器发现b作用域不在这里
}
编译器压根不知道 宏 的存在,预处理器直接进行了文本替换
关于const的疑问
#include<stdio.h>
int main()
{
const int x = 1;
const int& rx = x;//rx代表一个只读变量,这个变量所对应的内存空间是编译器为x常量分配的空间
int& nrx = const\_cast<int&>(rx);//nrx 对应的空间 和 rx一直,但是他没有只读属性
nrx = 5;
printf("x = %d\n", x);
printf("rx = %d\n", rx);
printf("nrx = %d\n", nrx);
printf("&x = %p\n", &x);
printf("&rx = %p\n", &rx);
printf("&nrx = %p\n", &nrx);
volatile const int y = 2; //不是真正意义上的常量
int\* p = const\_cast<int\*>(&y); //将y的地址的只读属性去掉
\*p = 6;
printf("y = %d\n", y);
printf("p = %p\n", p);
const int z = y; //编译不确定z的值,所以z是只读变量
p = const\_cast<int\*>(&z);
\*p = 7;
printf("z = %d\n", z);
printf("p = %p\n", p);
char c = 'c';
char& rc = c; // rc代表 c
const int& trc = c;//const引用他的类型不同的话,他会得到一个新的只读变量 trc
rc = 'a';
printf("c = %c\n", c);
printf("rc = %c\n", rc);
printf("trc = %c\n", trc);
return 0;
}
3、引用
引用的概念
- 引用作为 变量别名 而存在,因此在一些场合 可以代替指针
- 引用相对指针来说具有更好的 可读性 和实用性
void swap(int& a, int& b){
int t = a;
a = b;
b = t;
}
const 引用
- 在C++ 中可以声明 const 引用, const type& name = var;
- const 引用 让变量拥有 只读属性
int a = 4;
const int& b = a;
int\* p =(int\*)&b;
b = 5; //Error, 只读变量
\*p = 5; //OK. 修改变量 a 的值
- 当使用 常量 对 const引用进行初始化是,C++ 编译器会为常量值分配空间,并将引用作为这段空间的别名 使用常量对 const 引用初始化后将生产一个只读变量
#include <stdio.h>
int main()
{
const int& b = 1;
int\* p = (int\*)&b;
printf("b = %d\n", b);
printf("\*p = %d\n", \*p);
printf("p =%p\n", p);
// b = 5; //ERROR
\*p = 5;
printf("b = %d\n", b);
printf("\*p = %d\n", \*p);
printf("p =%p\n", p);
return 0;
}
引用的本质
- C++编译器在 编译过程中 用 指针常量 作为引用的 内部实现,因此引用所占的空间大小与指针相同。
- 从使用的角度,引用只是一个别名,C++为了实用性而隐藏了引用的存储空间这一细节
- 引用可以大多数情况下代替指针,可以尽可能的避开内存错误
关于引用的疑问
#include<stdio.h>
int a = 1;
struct SV
{
int& x;
int& y;
int& z;
};
int main()
{
int b = 2;
int\* pc = new int(3);
SV sv = {a, b, \*pc};
int& array[] = {a, b, \*pc};//&array[1] - &array[0] = 应该是4,数组\
所以在C++里面不支持引用数组
printf("&sv.x= %p\n",&sv.x);
printf("&sv.y= %p\n",&sv.y);
printf("&sv.z= %p\n",&sv.z);
delete pc;
return 0;
}
- 指针是一个变量 引用是一个变量的新名字
- const 引用能够生产 新的只读变量
- 编译时不能直接确定初始值的 const 表示符都是 只读变量
4、内联函数
- C++中推荐使用 内联函数替代宏代码片段
- C++中使用 inline 关键字声明内联函数
inline int func(int a, int b)
{
return a < b ? a : b;
}
- C++编译器可以讲一个函数进行内敛编译,被C++编译器内敛编译的函数叫做 内联函数
- C++编译器直接将函数体插入函数调用的地方
- 内联函数 替代 宏定义更加安全 , 宏代码片段由预处理器处理,进行简单的文本替换,没有任何的编译过程,因此可能出现副作用。
- 内联函数 没有 普通函数调用时的 额外开销(压栈,跳转,返回)
- inline只是一种请求,C++编译器 不一定满足函数的内联请求!!!
- 现代 C++ 编译器 能够进行编译优化,一些函数及时没有 inline声明,也可能被内敛编译
- 一些现代 C++编译器 提供了 扩展语法,能够对函数进行 强制内联,如:
g++ :_attribute((always_inline)) 属性 (attribute后面也有一个__打不出来)
MSVC: _forceinline
\_attribute\_((always_inline)) //g++
_forceinline //MSVC
C++ 中 inline 内联编译的限制:
- 不能存在任何形式的 循环语句
- 不能存在 过多的条件判断语句
- 函数体不能过于庞大
- 不能对函数进行取址操作
- 函数内敛声明 必须在调用之前
5、函数参数的扩展
- C++中可以在 函数声明时 为参数提供一个默认值
- 当函数调用没有 提供参数的值,则使用默认值
- 参数的默认值 必须在 函数声明中指定
- 参数的默认值必须 从右向左提供
- 函数调用时 使用了默认值,则后续参数 必须使用默认值
在C++中可以为函数提供 站位参数
- 占位参数 只有参数类型声明,而 没有参数名声明
- 一般情况下,在函数体内部 无法使用占位参数
- 占位参数与默认参数结合起来使用
int func(int x, int){
return x;
}
//...
func(1,2); //ok
函数占位参数 为了 兼容C语言程序 中可能出现的不规范写法,看下面的例子:
void func(int = 0, int = 0){}
int main(int argc, char \*argv[])
{
func();
func(1,2);
return 0;
}
6、函数重载分析
函数重载(Function Overload)
- 用同一个函数名定义不同的函数
- 当函数名和 不同的参数搭配 时函数的含义不同
- 函数重载 至少 满足下面的一个条件:
参数 个数 不同
参数 类型 不同
参数 顺序 不同
当 函数默认参数 遇上 函数重载会发生什么?
#include<stdio.h>
int func(int a, int b, int c = 0){
return a \* b \* c;
}
int func(int a, int b){
return a + b;
}
int main(int argc, char \*argv[])
{
int c = func(1, 2);//编译器会报错,他不知道该调用什么 ERROR
return 0;
}
![img](https://img-blog.csdnimg.cn/img_convert/850478e63a8aa9f0a861446300f36b93.png)
![img](https://img-blog.csdnimg.cn/img_convert/78f3cde3cab00546ef6f1fcfc7a07b75.png)
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!**
**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新**
**需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)**
**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618679757)**
b){
return a + b;
}
int main(int argc, char \*argv[])
{
int c = func(1, 2);//编译器会报错,他不知道该调用什么 ERROR
return 0;
}
[外链图片转存中...(img-UQzdIUUR-1715865139821)]
[外链图片转存中...(img-fIB0Xbpx-1715865139821)]
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!**
**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新**
**需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)**
**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618679757)**