翻译阶段
- 以实现定义方式,映射源文件的单独字节,为源字符集的字符。特别是以换行字符替代依赖OS的行尾指示符。以对应的单字节表示替换三标符。
- 删除行尾反斜杠和换行符
- 以空格字符替换注释;并分析语法。
- 执行预处理器。#include语句所引入的每个文件都经历上面4各过程,递归执行。此阶段结束,从源码移除所有预处理器指令。
- 将字符常量和字符串字面量所有字符及转义字符,从源字符集转换成执行字符集。
- 连接相邻的字符串字面量
- 编译。按照语法和语义分析记号,并将它们翻译成翻译单元。
- 链接。将翻译单元与外部引用所需库汇集成程序映像,它含有在其执行环境(OS)中执行的所需信息。
作用域
C包含以下作用域:块作用域(某个代码块)、文件作用域、函数作用域、函数签名作用域、声明点作用域。
类型支持
类型 | 用途 |
---|---|
size_t | sizeof运算符返回的无符号整型 |
ptrdiff_t | 指针相减返回的有符号整型 |
NULL | 空指针常量 |
offsetof | 从指定结构体类型的起始,到指定成员的字节偏移 |
变参
宏与类型 | 用途 |
---|---|
va_start | 令函数得以访问可变参数 |
va_arg | 访问下一个函数的可变参数 |
va_copy | 创造函数可变参数的副本 |
va_end | 结束函数可变参数的行程 |
va_list | 保有以上宏所需信息 |
错误处理
处理 | 用途 |
---|---|
errno | POSIX线程局域错误编号变量 |
assert | 断言 |
动态内存管理
函数 | 作用 |
---|---|
malloc | 分配内存 |
calloc | 分配并清零 |
realloc | 扩充之前分配的内存块 |
free | 归还之前分配的内存 |
aligned_alloc | 分配对齐内存 |
时间管理
函数 | 作用 |
---|---|
difftime | 计算时间差 |
time | 返回纪元开始经过的当前系统日历时间 |
clock | 返回未加工的程序启动时开始经过的处理器时间 |
asctime | 将tm转换成文本展示 |
ctime | 将time_t转换成文本展示 |
strftime | 将tm转换成自定义文本表示 |
gmtime | 返回UTC的机缘开始经过的日历时间 |
localtime | 本地时间表示的日历时间 |
mktime | 将日历时间转换成纪元开始经过的时间 |
CLOCKS_PER_SEC | 处理器每秒的时间秒 |
tm | 日历时间类型 |
time_t | 纪元开始的日历时间类型 |
clock_t | 从时间点开始的处理器时间类型 |
算法
函数 | 作用 |
---|---|
qsort | 快速排序 |
bsearch | 搜索元素 |
数学:
-
随机数生成
函数 作用 rand 生成伪随机数 srand 设置随机数生成器种子 -
复数
-
三角函数等常见函数
输入输出
文件操作
I/O 流是 FILE 类型对象,只能通过 FILE* 类型指针访问及操作(注意:在可能通过解引用合法的 FILE* 复制创建 FILE 类型局部对象时,在 I/O 函数使用这种副本的地址是未定义行为)。每个流与外部物理设备(文件、标准输入流、打印机、序列端口等)关联。
I/O 流能用于无格式和有格式的输入及输出。它们对本地环境敏感,并可在需要时提供宽/多字节转换。所有流都访问同一本地环境对象:最近 setlocale 所安装者。
在系统指定的需要访问设备的信息(例如 POSIX 文件描述符)外,每个流对象保有下列信息:
1) (C95)字符宽度:未设置、窄或宽。
2) 缓冲状态:无缓冲、行缓冲、全缓冲。
3) 缓冲区,可为外部的用户提供缓冲区所替换。
4) I/O 模式:输入、输出或更新(兼具输入与输出)。
5) 二进制/文本模式指示器。
6) 文件尾指示器。
7) 错误状态指示器。
8) 文件位置指示器( fpos_t
类型对象),对于宽字符流包含剖析状态( mbstate_t 类型对象(C95))。
9) (C11)在多个线程读、写、寻位或查询流时避免数据竞争的再入锁。
函数 | 作用 |
---|---|
fopen | 打开文件 |
freopen | 以不同名称打开既存的文件流 |
fclose | 关闭文件 |
fflush | 将输出流与实际文件同步 |
setbuf | 为文件流设置缓冲区 |
setvbuf | 为文件流设置缓冲区和其大小 |
fread | 从文件读取 |
fwrite | 写入到文件 |
fgetc,fgets | 从文件流读取一个字符或字串 |
fputc,fputs | 将字符或字串写入文件流 |
getchar,gets | 从stdin读取一个字符或字串 |
putchar,puts | 将字符或字串写入到stdout |
ugetc | 将一个字符送回文件流 |
scanf,fscanf,sscanf,vscanf,vfscanf,vsscanf | 从stdin,文件流或缓冲区读取格式化输入 |
printf,fprintf,sprintf,snprintf | 打印格式化输出到stdout、文件流或缓冲区 |
vprintf,vfprintf,vsprintf,vsnprintf | 打印格式化输出到stdout、文件流或缓冲区,使用可变参数列表 |
ftell | 返回当前文件位置指示值 |
fgetpos | 获取文件位置指示器 |
fseek | 将文件位置指示符移动到文件中的指定位置 |
fsetpos | 将文件位置指示器移动到文件中的指定位置 |
rewind | 将文件位置指示器移动 |
clearerr | 清除错误 |
feof | 检查文件结尾 |
ferror | 检查文件错误 |
perror | 将错误显示到stderr |
remove | 删除文件 |
rename | 重命名文件 |
tmpfile | 返回指向临时文件的指针 |
tmpnam | 返回唯一的文件名 |
读写模式:
模式 | 含义 | 解释 | 若文件已存在 | 若文件不存在 |
---|---|---|---|---|
r | 读 | 打开文件以读取 | 从头读 | 打开失败 |
w | 写 | 创建文件以写入 | 销毁内容 | 创建新文件 |
a | 后附 | 后附到文件 | 写到结尾 | 创建新文件 |
r+ | 读扩展 | 打开文件以读写 | 从头读 | 错误 |
w+ | 写扩展 | 创建文件以读写 | 销毁内容 | 创建新文件 |
a+ | 后附扩展 | 打开文件以读写 | 写到结尾 | 创建新文件 |
本地化支持
函数 | 作用 |
---|---|
setlocale | 获取和设置当前C本地环境 |
localeconv | 查询当前本地环境的数值及货币格式化细节 |
lconv | localeconv返回的细节化格式 |
注意事项:
- 指针:是间接引用,用于我们创建和销毁的复杂、持久对象。在初始化之前,指针是nullptr(即任意空间)。
字面量
- 修饰符
- 变量修饰符: register, const,
- 函数修饰符: inline,
- 访问限定符: public, protected, private
- 作用域: static, extern
- 局部/自动: 基于代码块
- 静态: 基于翻译单元(.cpp)和代码块(函数内部静态变量,只在函数内可见并初始化一次; 类内部则为类全局)
- 全局: 跨代码块和翻译单元
- 宏
- 声明与定义:声明不会有链接属性;不占内存空间。
工具:
-
预处理器:对
#
语句进行处理 - 编译器:将
.c++
翻译为.o
。此过程不涉及链接,外部声明姑且认为存在。- object文件,包含编译后的机器码和全局、静态变量。所有Object文件都是可重定位(未决定代码的内存地址)和未链接(未解决外部函数引用以及外部定义的全局数据)的。
-
库归档:将多个
.o
联合成.a
- 链接器:将
.a
,.o
链接成最终目标.exe
或.so
。解决所有外部依赖,存在以下结果:依赖未找到;重定义;找到并正确链接。- 动态链接库:是未完全链接(内存地址只在载入时确定)的。
附录
- 内存布局:
- 代码段:所有函数的可执行机器码
- 数据段:所有获得初始化的全局、静态变量(内存地址确定)
- BBS(Block started By Symbols):未初始化的全局和静态变量
- 只读数据段(Read Only Data Segment): 程序中定义的常量。整数常量常会直接嵌入到机器码(类似预处理操作),而不会存在于RODATA中。
- 程序运行堆栈: 由系统维护,开始于函数调用,结束于函数调用结束。存储3种数据:
- 调用函数的返回地址
- CPU寄存器的内容
- 局部变量
- 结构体/类内存布局: 如果类有虚函数即有虚函数表,每个实例。 虚函数表: | 基类虚函数表指针…| 本类虚函数指针… | | 虚函数表指针 | 基类内存布局 | 派生类内存布局 |
重回C/C++
MS Windows C++工具链
-
cl: C++编译器。支持C,C++, C++/CLI, C++/CX。cl也可进行代码分析:
cl /analyze demo.cpp
-
link: C++链接器。
-
lib: 用于创建和管理(Common Object File Format )对象文件的通用对象文件格式库。它还可以用于创建导出文件和导入库以便引入导出的定义。
-
editbin: 修改COFF二进制文件
-
dumpbin: 显示信息(如有关COFF二进制文件的符号表)
-
nmake: 读取和执行makefiles。类似Linux平台的make工具。
NMAKE只能通过Developer Command Prompt打开。它通过vcvars描述不同目标平台的环境变量(如工具、库、包含文件路径等)。
-
xdcmake: 用于处理含XML标签的文档注释的源码文件
-
rc:编译本地资源。
-
msbuild: 是构建管理工具。可创建项目文件(如vcxproj)。如
msbuild myproj.vcxproj /p:configuration=debug
。可指定生成事件、生成工具
cl编译器选项:
优化
选项 | 目标 |
---|---|
/O1 |
创建小代码。 |
/O2 |
创建快速代码。 |
/Ob |
控制内联展开。 |
/Od |
禁用优化。 |
/Og |
已弃用。 使用全局优化。 |
/Oi |
生成内部函数。 |
/Os |
代码大小优先。 |
/Ot |
代码速度优先。 |
/Ox |
不包含/GF 或/Gy. 的/O2 子集 |
/Oy |
省略帧指针。 (仅限 x86) |
/favor |
生成针对一个指定体系结构或一系列体系结构进行优化的代码。 |
代码生成
选项 | 目标 |
---|---|
/arch |
使用 SSE 或 SSE2 指令生成代码。 (仅限 x86) |
/clr |
生成要在公共语言运行时上运行的输出文件。 |
/EH |
指定异常处理模型。 |
/fp |
指定浮点行为。 |
/GA |
针对 Windows 应用程序进行优化。 |
/Gd |
使用 __cdecl 调用约定。 (仅限 x86) |
/Ge |
已弃用。 激活堆栈探测。 |
/GF |
启用字符串池。 |
/Gh |
调用挂钩函数 _penter 。 |
/GH |
调用挂钩函数 _pexit 。 |
/GL |
启用全程序优化。 |
/Gm |
已弃用。 启用最小重新生成。 |
/GR |
启用运行时类型信息 (RTTI)。 |
/Gr |
使用 __fastcall 调用约定。 (仅限 x86) |
/GS |
检查缓冲区安全性。 |
/Gs |
控制堆栈探测。 |
/GT |
支持使用静态线程本地存储分配的数据的纤程安全。 |
/guard:cf |
添加控制流防护安全检查。 |
/guard:ehcont |
启用 EH 继续元数据。 |
/Gv |
使用 __vectorcall 调用约定。 (仅限 x86 和 x64) |
/Gw |
启用全程序全局数据优化。 |
/GX |
已弃用。 启用同步异常处理。 改为使用 /EH 。 |
/Gy |
启用函数级链接。 |
/GZ |
已弃用。 启用快速检查。 与) (相同 /RTC1 |
/Gz |
使用 __stdcall 调用约定。 (仅限 x86) |
/homeparams |
强制将传入寄存器的参数写入其在函数入口的堆栈上的位置。 此编译器选项仅适用于 x64 编译器 (本机编译和跨平台编译) 。 |
/hotpatch |
创建可热修补的映像。 |
/Qfast_transcendentals |
生成快速先验。 |
/QIfist |
已弃用。 当需要从浮点型转换为整型时,取消调用 Helper 函数 _ftol 。 (仅限 x86) |
/Qimprecise_fwaits |
删除 fwait 块内 try 的命令。 |
/QIntel-jcc-erratum |
缓解 Intel JCC 错误微代码更新对性能的影响。 |
/Qpar |
启用循环的自动并行化。 |
/Qpar-report |
启用自动并行化的报告级别。 |
/Qsafe_fp_loads |
将整数移动指令用于浮点值,并禁用特定浮点加载优化。 |
/Qspectre |
为 CVE 2017-5753 启用缓解,适用于一类 Spectre 攻击。 |
/Qspectre-load |
为每个加载指令生成序列化说明。 |
/Qspectre-load-cf |
为每个加载内存的控制流指令生成序列化说明。 |
/Qvec-report |
启用自动矢量化的报告级别。 |
/RTC |
启用运行时错误检查。 |
/volatile |
选择如何解释 volatile 关键字。 |
输出文件
选项 | 目标 |
---|---|
/doc |
将文档注释处理到一个 XML 文件中。 |
/FA |
配置程序集列表文件。 |
/Fa |
创建程序集列表文件。 |
/Fd |
重命名程序数据库文件。 |
/Fe |
重命名可执行文件。 |
/Fi |
指定预处理输出文件名。 |
/Fm |
创建映射文件。 |
/Fo |
创建对象文件。 |
/Fp |
指定预编译头文件名。 |
/FR , /Fr |
名称生成 .sbr 的浏览器文件。 |
预处理器
选项 | 目标 |
---|---|
/AI |
指定在解析传递到 #using 指令的文件引用时搜索的目录。 |
/C |
在预处理期间保留注释。 |
/D |
定义常数和宏。 |
/E |
将预处理器输出复制到标准输出。 |
/EP |
将预处理器输出复制到标准输出。 |
/FI |
预处理指定的包含文件。 |
/FU |
强制使用文件名,就像它已被传递到 #using 指令一样。 |
/Fx |
将插入的代码与源文件合并。 |
/I |
在目录中搜索包含文件。 |
/P |
将预处理器输出写入文件。 |
/U |
移除预定义宏。 |
/u |
移除所有的预定义宏。 |
/X |
忽略标准包含目录。 |
语言
选项 | 目标 |
---|---|
/constexpr |
constexpr 在编译时控制计算。 |
/openmp |
#pragma omp 在源代码中启用。 |
/vd |
取消或启用隐藏的 vtordisp 类成员。 |
/vmb |
对指向成员的指针使用最佳的基。 |
/vmg |
对指向成员的指针使用完全一般性。 |
/vmm |
声明多重继承。 |
/vms |
声明单一继承。 |
/vmv |
声明虚拟继承。 |
/Z7 |
生成与 C 7.0 兼容的调试信息。 |
/Za |
禁用 C89 语言扩展。 |
/Zc |
指定下的标准行为 /Ze 。 |
/Ze |
已弃用。 启用 C89 语言扩展。 |
/Zf |
在并行生成中改善 PDB 生成时间。 |
/ZH |
为调试信息中的校验和指定 MD5、SHA-1 或 SHA-256。 |
/ZI |
将调试信息包含在与“编辑并继续”兼容的程序数据库中。 (仅限 x86) |
/Zi |
生成完整的调试信息。 |
/Zl |
删除文件中的默认库名称 .obj 。 |
/Zp n |
封装结构成员。 |
/Zs |
只检查语法。 |
/ZW |
生成要在 Windows 运行时上运行的输出文件。 |
链接
选项 | 目标 |
---|---|
/F |
设置堆栈大小。 |
/LD |
创建动态链接库。 |
/LDd |
创建调试动态链接库。 |
/link |
将指定的选项传递给 LINK。 |
/LN |
创建 MSIL 模块。 |
/MD |
使用 msvcrt.lib 编译以创建多线程 DLL。 |
/MDd |
使用 msvcrtd.lib 编译以创建调试多线程 DLL。 |
/MT |
使用 libcmt.lib 编译以创建多线程可执行文件。 |
/MTd |
使用 libcmtd.lib 编译以创建调试多线程可执行文件。 |
杂项
选项 | 目标 |
---|---|
/? |
列出编译器选项。 |
@ |
指定响应文件。 |
/analyze |
启用代码分析。 |
/bigobj |
增加 .obj 文件中可寻址节的数目。 |
/c |
编译但不链接。 |
/cgthreads |
指定用于优化和代码生成的 cl.exe 线程数。 |
/errorReport |
已弃用。 错误报告由 Windows 错误报告 (WER) 设置控制。 |
/FC |
在诊断文本中显示传递给 cl.exe 的源代码文件的完整路径。 |
/FS |
强制写入 PDB 文件,以便通过 MSPDBSRV.EXE 进行序列化。 |
/H |
已弃用。 限制外部(公共)名称的长度。 |
/HELP |
列出编译器选项。 |
/J |
更改默认 char 类型。 |
/JMC |
支持本机 c + + 仅我的代码调试。 |
/kernel |
编译器和链接器将创建可在 Windows 内核中执行的二进制文件。 |
/MP |
同时生成多个源文件。 |
/nologo |
取消显示登录版权标志。 |
/sdl |
启用更多安全功能和警告。 |
/showIncludes |
在编译期间显示所有包含文件的列表。 |
/sourceDependencies |
列出标头、模块和其他源依赖项。 |
/Tc |
指定 C 源文件。 |
/TC |
指定所有源文件均为 C。 |
/Tp |
指定 C++ 源文件。 |
/TP |
指定所有源文件均为 c + +。 |
/V |
已弃用。 设置版本字符串。 |
/w |
禁用所有警告。 |
/W0 , /W1 , /W2 , /W3 , /W4 |
设置输出警告级别。 |
/w1 , /w2 , /w3 , /w4 |
针对指定的警告设置警告级别。 |
/Wall |
启用所有警告,包括默认情况下禁用的警告。 |
/wd |
禁用指定的警告。 |
/we |
将指定的警告视为错误。 |
/WL |
在从命令行编译 C++ 源代码时启用错误消息和警告消息的单行诊断。 |
/wo |
仅显示指定的警告一次。 |
/Wv |
禁用更高版本的编译器引入的警告。 |
/WX |
将警告视为错误。 |
/Yc |
创建 .PCH 文件。 |
/Yd |
已弃用。 将完整的调试信息放在所有对象文件中。 改为使用 /Zi 。 |
/Yl |
创建调试库时插入 PCH 引用。 |
/Yu |
在生成期间使用预编译头文件。 |
/Y- |
忽略当前生成中的所有其他预编译头编译器选项。 |
/Zm |
指定预编译头内存分配限制。 |
/await |
) 扩展启用协同程序 (可恢复的函数。 |
/source-charset |
设置源字符集。 |
/execution-charset |
设置执行字符集。 |
/utf-8 |
将源和执行字符集设置为 UTF-8。 |
/validate-charset |
仅验证 UTF-8 文件的兼容字符。 |
/diagnostics |
控制诊断消息的格式。 |
/permissive- |
设置标准一致性模式。 |
/std |
C + + 标准版本兼容性选择器。 |
实验性选项
实验性选项只能由某些版本的编译器支持。 它们在不同的编译器版本中也可能具有不同的行为。 对于试验性选项,通常是最好的文档,也是 Microsoft c + + 团队博客。
选项 | 目标 |
---|---|
/experimental:module |
启用实验性模块支持。 |
/experimental:preprocessor |
已弃用。 启用实验相容预处理器支持。 使用 /Zc:preprocessor |
弃用并删除的编译器选项
选项 | 目标 |
---|---|
/clr:noAssembly |
已弃用。 改用 /LN (创建 MSIL 模块) 。 |
/errorReport |
已弃用。 错误报告由 Windows 错误报告 (WER) 设置控制。 |
/Fr |
已弃用。 创建无局部变量的浏览信息文件。 |
/Ge |
已弃用。 激活堆栈探测。 默认已启用。 |
/Gm |
已弃用。 启用最小重新生成。 |
/GX |
已弃用。 启用同步异常处理。 改为使用 /EH 。 |
/GZ |
已弃用。 启用快速检查。 改为使用 /RTC1 。 |
/H |
已弃用。 限制外部(公共)名称的长度。 |
/Og |
已弃用。 使用全局优化。 |
/QIfist |
已弃用。 曾用来指定如何从浮点类型转换到整型类型。 |
/V |
已弃用。 设置 .obj 文件版本字符串。 |
/Wp64 |
已过时。 检测 64 位可移植性问题。 |
/Yd |
已弃用。 将完整的调试信息放在所有对象文件中。 改为使用 /Zi 。 |
/Zc:forScope- |
已弃用。 在 for 循环范围中禁用一致性。 |
/Ze |
已弃用。 启用语言扩展。 |
/Zg |
在 Visual Studio 2015 中移除。 生成函数原型。 |
xdcmake 注释文档工具中的特殊标记:
通常使用Doxygen替代。
- code: 表示为代码
- example: 示例代码
- exception: 表明代码会抛出的异常
- cref: 可交叉引用的
- include:引用文档
- list: 列表项
- para: 段落
- param:方法的参数名说明
- permission:指明权限
- remarks:成员说明。如同doxygen 中的description
- returns:返回值的说明
- see:参见,文档内的引用
- seealso: 同see,但可跨文档引用
- summary:摘要信息。