关于c语言与c++语言的头文件

    技术2022-05-11  118

    在c/c++语言中的头文件其实是为了搜寻对应的类型和函数信息的比如在头文件中可以声明一个函数,但这个函数可能定义在任何地方比如一个静态库或者动态导入库lib中,或者可以直接以原代码的方式写在cpp/c文件中头文件提供的服务叫做类型映射(phototype)

    函数在c/c++语言中也是一种类型函数在声明的时候其实仅仅是说明了对应的函数调用协议,函数名称和参数类型这样就可以明确的指导编译器如何创建这个函数对应的调用代码而寻找这个函数的工作交给了链接器注意 编译器在vc里边叫做cl,链接器在vc里边叫做link。

    cl负责生成obj,每一个cpp/c文件会生成一个obj文件这个obj里边包含了直接由c/cpp源程序所生成的汇编代码,这个c/cpp文件需要查找的符号(这个后面再说)

    link其实和咱们上微机原理汇编课的时候用的Link很像他负责将每一个obj中的符号查找表中的东西转换为一个地址这个地址就是最后编译完成后的exe文件的函数对应这个函数的入口地址。

    符号,就是这个函数或者对象通过编译器后所产生的名称在c语言中一个符号由这个函数或者这个对象的名称和这个函数的调用协议组成这也是为什么c语言不支持重载的原因(还记得重载吧?重载就是参数类型或个数不同,参数和个数都相同的叫做重写,重写只能用在类的函数的继承中)而c++会在每一个函数的前后添加一堆用于表示这个函数的调用方法所属类型,名字空间和调用参数类型等的大量字符用来区分每一个函数比如一个函数int Test(); 根据不同的命名方法可能被不同的命名如果到定义了extern "C" 如下:extern "C" int Test();这个函数就被vc编译器按c语言的方式命名为 _Test 其中的前划线 _表示这个函数的调用协议为__cdecl Test就是这个函数的名称如果使用vc编译器直接编译这个函数int Test();他就被当作int __cdecl Test(void); 编译成  ?Test@@YAHXZ 其中的? 和 @@YAHXZ都是编译器加上去的 ? 和 @@YAH 是用来表示调用协议的 其中的H为返回值是int X表示没有参数。 Z是函数名称结束修饰

    调用协议指函数的参数传递使用的方式有__cdecl __fastcall __stdcall __thiscall 等__cdecl 是c语言的调用方式__fastcall 使用寄存器传递参数__stdcall 使用栈传递参数,并且其压栈顺序为从右到左,由被调用函数来清除栈__thiscall 是类对象的方法调用方式,这种调用方式不能直接由程序指定

    如果一个函数的是被实现在cpp或者c文件中的时候,就必须保证这个cpp或者c文件所产生的符号与这个函数的声明所产生的符号相同,否则链接器在链接的时候就会发生无法找到符号的错误

    如何保证这个符号是相同的呢?只要在cpp或者c文件中包含这个头文件或者如果能保证所生成的符号相同则根本就不用h文件也能工作比如如下程序

    // 这是main.cpp文件的东西int Test();

    int main(){ Test();}

    // 这是test.cpp文件的东西int Test(){ return 1;}这里就完全没有用头文件

    注意事项:1。如果是使用了c文件作为函数的载体而编译器为微软的vc,需要在h文件中添加extern "C"通知编译器使用c的命名规则最好使用判断#ifdef __cplusplusextern "C" {#endif

    ... 函数声明...

    #ifdef __cplusplus}#endif这样在c编译器上也能使用这个头文件了2。c/cpp文件与头文件名称无关3。如果一个头文件中定义了一个结构或者类,那么在h文件中最好使用防止多次包含的#ifndef __XXX__H__#define __XXX__H__

    ... //类或结构定义class a{ ...};...

    #endif这里的XXX就是这个头文件的名称,这个名称是可以随便起的,只要不起重。但c/cpp文件中不需要添加这些东西

    或者如果使用了vc6作为编译器它支持#pragma once在h文件的最前面写上这句话就可以保证这个头文件只会被处理一遍


    最新回复(0)