# 【CCG】C风格编程 作者:wallace-lai
发布:2024-02-25
更新:2024-03-04
## 规则1:优先使用C++而不是C 这是因为: (1)C++提供比C更好的类型检查(更安全)和更多的写法支持(更灵活); (2)C++为高级编程语言提供了更好的支持,并往往生成更高效的代码; ## 规则2:如果必须使用C,请使用C和C++的公共子集,并以C++的方式编译C代码 - **如果有完整的C源代码可用** 这个时候基本没什么大问题,唯一可能需要修改的是C源代码中不是C和C++公共子集的那部分代码。 - **如果没有完整的C源代码** 此时,需要遵循以下几点原则: (1)使用C++编译`main`函数; 主要是因为C++编译器会生成一些在`main`函数启动之前执行的代码(比如调用全局(静态)对象的构造函数),这个时候你只能选择C++编译器。 (2)使用C++编译器链接程序; (3)使用同一供应商的C和C++编译器,它们应该具有相同的调用约定; 这个主要是**为了保证ABI的兼容性**,比如函数调用时参数的分配顺序、参数的传递、由调用方还是被调方处理函数栈等等。 ## 规则3:如果必须使用C作为接口,则在调用此类接口的代码里使用C++ 与C相比,C++支持函数重载。这意味着可以定义名字相同但参数不同的函数。为了支持函数重载,C++编译器会将函数参数的类型和数目也编码到函数名称中,这个过程被称为“名字重编”。并且每个C++编译器都可能有自己的特定编码方式,因为这一过程没有被标准化。 为了在C++中调用C函数,可以使用`extern "C"`链接说明符,用于告知C++编译器不要将这些函数名重编。使用链接说明符后,你既可以在C++中调用C函数,也可以在C函数中调用C++函数。 具体可行的实践方法如下: (1)在每个函数前加说明符 ```cpp extern "C" void foo(int); ``` (2)一个作用域内的每个函数 ```cpp extern "C" { void foo(int); double bar(double); } ``` (3)整个头文件,当使用C++编译器时,宏`__cplusplus`将被定义 ```cpp #ifdef __cplusplus extern "C" { #endif void foo(int); double bar(double); #ifdef __cplusplus } #endif ``` 在工程实践中,方法(3)是最常见的。