C和C++知识整理

byzhj 561 0
温馨提示

本篇为windows开发的第二篇,上一篇为《vb.net和C#知识整理》,因为c生万物,所以要学底层最重要的知识

一基础部分

0.历史

  • 1995-1998年,ansi的c++98标准发布
  • 2003,c-Primier-plus的版本
  • 2011,第二个正式版,有右值引用、自动类型推断,规定stl的统一命名空间,委托构造函数
  • 2014,做了些修复
  • 2017,inline内联函数(另一个作用:初始化类的静态变量)、
  • 2020,线程

 

1.C++的基础部分

  • c的前置知识:面向过程,只有函数和结构体
    • 预编译#:引入头文件或宏指令
      • 宏指令#define:常用来定义常量
    • system():调用系统命令行的命令
  • 命名空间:全限定名,c+沿用了。
    • 目的:防止多头文件下的函数冲突
    • using xx:限定空间,否则要引用空间名::

 

  • 代码块:限定内存区域
    • 全局变量:类似于JavaScript,并且存在作用域
      • 全局访问:使用指针
      • 访问冲突:使用::全限定名

 

  • 枚举:static final的常量
    •  使用:::代替.
    • C和C++知识整理

 

  • 结构体:声明一块自定义类型的内存
    • 声明struct xx{}:至少的大小和基础类型
    • 使用xx.property:构造一块类似于对象的引用
    • 内存:存在栈里。

 

  • std命名空间下的:集合、输入输出、数据结构
    • array<int,length>:拥有方法size()、
    • static_cast<int>:
    • vector<int> xx:接近于java的arraylist用法,可初始化大小和数组,但不用new分配空间
      • 新特性:clear()清除数组、push_back()自动扩容相当于java的add()、empty()是否空
    • cout和cin:用符号<<进行操作
    • hex、oct:等格式化输出数据
    • unique_ptr:唯一性的指针,
      • 初始化同java:{new int[]{}或类},make_unique<泛型>(值)
      • reset():释放内存,清除指针值。
      • get():返回他的指针地址给指针。
      • release():释放内存,返回原始的指针地址。
      • 转移:move()来转移指针指针
    • share_ptr:共享指针,但是需要所有都释放
      • unique():是否唯一指针
      • use_count(): 返回几个使用他的指针
      • reset():如果最后一个则释放

 

  • 字符串:是面向对象封装的类型
    • 不同点:访问是通过下标[]
      • find=charat()
    • 万物转字符串:std::to_string()
    • 字符串函数:std::stoi()转整数、stoxx直接转某个类型
    • C和C++知识整理
    • wchar_t类型数组:是一个宽字节16字节一个字符——相当于String底层
    • C和C++知识整理
    • Stringstream:以流方式操作字符串
      • 对比:十分类似stringbuffer

 

  • 函数:同主流语言,特别是typescript
    • 参数:可令指针为传入和返回参数,同java传入引用类型
    • 函数指针:类似于JavaScript的函数表达式设计
    • sizeof()是一个编译器识别的常量,只能根据定义推断。
    • 重载:同java,但是指针和数组引用是一样的。
    • C和C++知识整理
    • 常量指针:const,只读不允许修改引用值。
    • 默认参数:只能放在最后面
    • 不定参数:使用宏库<cstdarg>收集指针va_start
    • 本质:存在代码区(类似于方法区),栈地址固定。

 

  • 函数2:
    • 右值引用:存放在临时空间的没有声明的变量的引用&,例如函数返回值、计算表达式,不能写入的变量
      • 作用:避免复制,可以用于函数参数
      • C和C++知识整理
    • 引用参数:尽量加const,这样在接右值或不正确类型时能生成临时变量。
      • C和C++知识整理
      • C和C++知识整理
    • 指针参数:使用时要一直带着*,这叫解引用
      • C和C++知识整理
    • 返回引用类型:也应该用const,这样能限制直接修改对象的值。注意:他不能返回函数里的临时对象,除非new一份。
      • C和C++知识整理
    • 总体原则:不修改的用const,修改的不加
      • C和C++知识整理
    • 函数模板:相当于是泛型方法
      • 在函数上加temlpate<typename t1>,返回类型不确定可以为auto或decltype(auto)
    • C和C++知识整理
    • C和C++知识整理
    • 本质:当传入参数不同调用的call是不同的函数指针(由编译器来生成)。
    • 具体化:不使用模板而是自定义的定义<>
      • C和C++知识整理

 

  • decltype():根据括号里的值进行类型推断
    • 规则1、2:可以是函数返回值、已定义变量类型
    • 规则3:存在表达式左值引用或增加()时,则是创建引用类型。如果是右值或普通变量则是原始类型
    • C和C++知识整理
    • 规则4:不执行括号里的计算值。
    • 用法:配合auto使用推导函数的返回值。
    • C和C++知识整理
    • decltype(auto):引用即引用,指针即指针。
    • C和C++知识整理
    • 区别:对于指针的引用创建有不同
    • C和C++知识整理
    • 拖尾函数:强制使用引用auto bigger(int& a,int &b)->int&

 

  • 联合体:union
    • 联合体更适合在内存有限的情况下,需要同时保存多个不同类型的变量,但是只能存储其中一个变量的值的情况;
    • 很少用
    • 内存对齐:要按最大基本类型的大小对齐
    • C和C++知识整理

 

  • 面向对象
    • 构造函数:就是执行函数并分配内存。
    • explicit:禁用类型转换,一般用于函数前,则调用时无法隐转
      • 构造函数:则此对应类在初始对象时无法直接从 vec.push_back(10); // 错误:无法进行隐式转换
      • 只有使用static_cast<int>(t);
    • default:就是提高析构和默认构造函数效率的语法糖。

 

 

  • 运算符重载
    • 作用:类似于函数,在成员内默认左边就是类对象,友元函数能操作对象变量。
    • 说明:有严格的限制,三种情况:成员函数、全局函数、友元函数
    • int operator =()

 

 

  • 多重继承:
    • 虚函数:virtual和override(只是为了让编译器检查是否参数一致)
    • 作用:通常使用基类的指针来调用(向上转型)
    • 虚类:解决多重继承中的成员重复问题。否则只能用命名空间A::var
    • 析构函数:得将析构函数设为虚函数,因为会触发所有析构函数。
    • 纯虚函数:如下图,即是
      • C和C++知识整理
    • typeid:类似于typeof+instanceof获取运行时数据类型,但不能用于指针、数组、函数
      • C和C++知识整理
    • 抽象类:就是有virtual的纯虚函数的类
    • 友元类:允许另一个类访问自己的私有成员和保护成员的类。
      • C和C++知识整理
      • 类似于定义在外边的内部类A中声明b,则b能使用A,
      • 友元函数:能
    • 函数调用约定:
      • cdecl:能从右往左入栈,支持多参数
      • 区别:调用者恢复栈平衡。
      • C和C++知识整理

 

 

2.指针的顶级理解

  • 基本构成:地址和大小
    • 定义类型:int*指定一个4字节大小的变量的内存开头地址:int* x=&A,定义和使用赋值不一样。
    • 使用:存地址取地址运算
      • p取址符号&:=&A取得一个命名变量的地址
      • p地址变量直接赋值:=0x0001改地址
      • *p取变量间接赋值:=6666给指向地址的值赋值
      • p指针运算:是按类型加指定大小例如int就是4字节
      • C和C++知识整理

 

  • 指针:
    • 指针本身大小:4字节,表达总共的内存寻址范围:32位4gb
    • 意义:大小由定义类型决定,但可操作任一一块地址——使用取址&A
    • 定义和使用:定义一般直接给地址值,使用可以取或直接赋值取或间接赋值
    • 指针的括号:
      • 数组指针:(*ptr),可以指向数组[5],指向二维数组则长度为其一维的长度[][6]——正经的类型int[]*
      • *ptr:指向数组[5]表示是指针数组
      • C和C++知识整理

 

  • 内存:
    • 分配:malloc(字节大小)返回该块内存的指针、calloc(,倍数)指定数量、relloc(2,8)重新指定大小
      • new int:分配出一块内存空间在堆里
      • C和C++知识整理
    • 释放:free(指针)——必须清0不能出现野指针
      • delete 指针:释放该指针内存,删除一段数组要用 delete[] 指针,删除对象也要delete[]
    • 复制:memcpy(目的指针,指针,字节)、memset(地址,值,字节大小)
    • 区别:推荐用new、delete[]
      • 对于对象的区别:不仅删除,而且会调用构造函数和析构函数。
      • C和C++知识整理

 

  • 继承的内存机制:
    • 继承子类对象里面有父类的内容。因为执行了父类构造器。
    • 虚函数表:类为单位,继承时改写每个虚函数表中元素的值(函数地址),
    • dynamic_cast<目标>:强制动态转换,一般用于父类转子类,即向下转型

 

 

  • 类的底层机制:
    • 虚函数表:以类为单位,所有虚函数的指针在里面,对象new出来后会有一个指针vptr对象中。
      • C和C++知识整理
      • C和C++知识整理
      • C和C++知识整理
      • 总结:跟java差不多,子类的虚表重写方法会覆盖原来虚函数地址,否则不会。
    • 类信息:类似于java中的方法区
      • C和C++知识整理

 

 

  • 堆栈:
    • 引用:就是一个指针,只不过不能手动改变地址。
    • 栈管运行方法(main区),堆管数据(手动管理)。
    • 函数栈:函数调用会生成调用栈,上层可以访问底层的变量。

 

3.cpp的编译

  • 头文件h:存放函数和全局变量声明的文件
    • extend:声明一个外部变量,函数默认是extend,会让编译器从另一处找到代码定义地址。函数名本质上就是一个代码区地址。
      • extend "C" xx:定义一个c风格的声明
      • 一般全局变量不需要用,局部变量要用
      • C和C++知识整理
      • C和C++知识整理
    • lib文件:二进制文件
    • 使用:在源码里引入头文件,相当于让编译器知道是个引用。
      • 编译:添加依赖项,或手动引入二进制#pragma comment(lib,"xx.lib")
      • 只能使用一次:#pragma once
    • 定义:只定义方法,也可以定义inline和static变量和方法,会直接存到全局区,同名源文件引入后并实现该定义。
    • 宏定义#ifndef MYCLASS_H #define MYCLASS_H防止被多次重复引用
      • 作用:就是定义一些常量、预处理指令
      • 预定义宏:程序的常规常量,例如_func_等
    • 断言:assert()
      • 作用:编译检查某些表达式的bool值,
      • 使用:需要<cassert>库,取消:#define nodebug

 

  • 源文件:
    • 代码区:存放函数的内存,类似于只放函数的堆,只读不能修改(因为没用变量)
    • 通信:依靠引入同一个头文件实现。

 

  • 编译器:
    • gnu c++:开源,但代码庞大
    • clang:使用llvm前端,苹果出品
    • mvc++:vs专属
    • 链接属于编译后端

 

  • llvm详解:
    • IR:负责连接编译
      • 表现形式:ll形式——人能看,特征为
    • 编译器前端
      • 语法提取:
      • 语法分析:解析成语法生成树
    • 后端:

 

  • 项目构建:就是管理依赖、编译、运行配置的工具
    • cmake:使用makelist配置,生成ninja或makefile文件
    • vs project:
    • makefile和ninja:根据特定语法规则进行编译项目

 

 

4.windows的接口

 

5.进阶多线程

 

6.网络库(cgi)

  • winsocket:

 

7.汇编

  • 基础概念:
    • []:代表间接寻址

 

  • 寄存器
    • eax下:通用的寄存器
    • esp、ebp:与函数调用栈有关,ebp是记录函数中断地址
    • ecx:用于循环的局部变量。
    • C和C++知识整理

 

 

  • 指令:
    • lea:专门存地址
    • imul:三个参数时可以指定存放地址
    • add、sub、inc、dec:加减后放到第一个操作数地址

 

 

  • 栈结构:栈顶与地址增加方向相反
    • call之前:
      • 把参数复制压入栈中,
    • call时:
      • 压入ebp和esp,esp随时指向栈顶
      • 压入callee-saved寄存器包括ebx,edi和esi
      • 将返回的执行结果保存在eax中
      • 将callee-saved寄存器复原
      • _stdcall栈平衡:由调用函数来栈平衡ret 8
    • call之后:
      • ebp用来恢复调用者的基址寄存器值。
      • _cdecl栈平衡:由调用者实现栈平衡——esp要向下移动,把多余的参数压栈出掉。
      • _fastcall:通过eax和edx传参,堆栈平衡由调用者维护。
      • _thiscall:类访问的默认方式

 

 

8.dll动态链接库

  • 概念:pe格式的二进制文件,应用程序用lib文件(内存地址)链接到dll的函数库
  • 对比:类似于jar包,内容是多个类文件,可被动态加载到内存中被引用。
    • 区别:dll是进程共享、但class只能线程共享。dll是平台相关常驻内存,class是平台无关动态加载。
    • 相似:都能被共享,都能节省内存,都是为了节省代码。
  • 开发:编写源码文件—编写同名头文件(需要用_declspec字段暴露)—编译项目生成lib、dll文件
  • 使用:导入命名空间(头文件)—引用链接库—使用方法
  • 工具:Dumpbin
    • 查看导出:dumpbin -exports xxx.dll
    • 查看导入:dumpbin -imports xxx.exe

 

 

9.Hook开发

  • 基本概念:hook就是修改dll文件内容执行额外代码。内核级别的hook有一些是加密的,但也有很多是开放api的,例如进程拦截等。
    • 详情参考这篇文章
    • 微软不允许,否则会吊销驱动签名。

 

  • 内存注入:调用api,修改内存数据,需要确定基址
    • 缺点:容易被检测到

 

  • 工具:aheadlib
    • 功能:根据输入DLL的导出表生成劫持源码。

 

10.逆向工程

  • 游戏外挂
    • ce:能搜索进程中的内存数据
      • 变化数据:
      • 精度确认:
      • 汇编调试台:查看内存区域
    • x32dbg:

 

  • ida:

 

二.框架部分

1.mfc

 

2.qt

独立了,请查阅:

 

3.h.264和ffmpeg

 

 

三.图形开发

0.前言

  • 图形渲染:底层调用api是openGL等库操作硬件显卡

 

  • 常见的引擎:
    • 浏览器:webgl
    • 桌面:
    • 游戏引擎:unity3d、

 

1.openGL

 

2.DirectX

 

四.项目

1.加密播放器

  • 基本库

 

2.qt的天气预测系统

 

3.音视频系统开发

 

  • 基本库

 

  • 客户端

 

  • 服务端

 

4.IM后台

 

 

5.远程控制

请跳转:编辑文章 “远控” ‹ 抱一只橘 — WordPress (byzhj.com)

发表评论 取消回复
表情 图片 链接 代码

分享