C++编译与链接-创新互联

编译
  • 编译过程
    首先,编译器会执行预处理,也就是所有以"#"开头的预处理语句。
    ->优化阶段->生成汇编并转换到机器语言->生成obj文件
    其中每个cpp文件都是单独的编译单元,都是独自生成相对的obj文件
    后期才通过linker进行相互的链接。

    发展壮大离不开广大客户长期以来的信赖与支持,我们将始终秉承“诚信为本、服务至上”的服务理念,坚持“二合一”的优良服务模式,真诚服务每家企业,认真做好每个细节,不断完善自我,成就企业,实现共赢。行业涉及OPP胶袋等,在重庆网站建设公司网络营销推广、WAP手机网站、VI设计、软件开发等项目上具有丰富的设计经验。
  • 预处理相关
    大致有#include:单纯的将头文件内的所有文本复制到所在的位置。
    #define:单纯的文本替换。
    #if:进行条件判断,若满足条件,则if所包含的文本有效,反之则无效。
    预处理相关设置:
    1 生成预处理后的文件,但不能生成obj生成预处理后的文件
    2 生成汇编代码文件在这里插入图片描述
    3 设置优化级数,使生成的obj、asm等文件不包含优化代码
    在这里插入图片描述
    优化等级与runtime check挂钩在这里插入图片描述

链接
  • 链接过程:

首先,要理解链接是将多个obj文件链接为一个exe文件,并解决在某个文件中引用另一个文件中的符号相关的问题。
链接时,linker首先决定各个obj文件在最终exe文件中的位置,然后访问所有obj文件的地址表,将其全部地址进行重定向,然后遍历所有obj文件中未解决的符号,生成未解决符号表,并在符号表中查找匹配的符号,将未解决符号表填补完成,最后对每个obj文件进行排序即完成。

  • 链接方式:
    1 静态链接:在链接时,就查找obj中缺失的目标函数,再去静态库中查找相应的obj对象,直接包含在程序内,运行时不用再次查询。但这里在库中查找的obj对象是一整个,也就是说即使只使用了它其中一个函数,还是会包含obj中其他所有的函数,导致内存大量浪费;且每次更新库,都需要将库重新编译并链接一遍。但优点在于运行时不用查询,运行速度快。
    2 动态链接:在运行时,检测到未解决符号,再去查找包含相应符号的obj文件,并且一个obj只用加载一次,空间使用率高,且更新时不用再次编译链接。但运行速度比不上静态库。
    下面是动态链接的过程:
    假设现在有两个程序program1.o和program2.o,这两者共用同一个库lib.o,假设首先运行程序program1,系统首先加载program1.o,当系统发现program1.o中用到了lib.o,即program1.o依赖于lib.o,那么系统接着加载lib.o,如果program1.o和lib.o还依赖于其他目标文件,则依次全部加载到内存中。当program2运行时,同样的加载program2.o,然后发现program2.o依赖于lib.o,但是此时lib.o已经存在于内存中,这个时候就不再进行重新加载,而是将内存中已经存在的lib.o映射到program2的虚拟地址空间中,从而进行链接(这个链接过程和静态链接类似)形成可执行程序。

  • 库相关
    1 编写库:
    ①新建空项目
    ②编写相应的.h和.cpp文件实现功能(具体待以后总结)在这里插入图片描述
    ③项目属性中设置在这里插入图片描述
    ④build过后,lib文件就生成了
    2 引用库:
    将要使用库的项目中新建两个文件夹(不建也可以)include和lib
    将上面编写的.h和.cpp复制到inclde中,lib复制到lib中
    在包含目录中添加包含.h和.cpp的文件夹路径在这里插入图片描述
    附加库目录中添加lib的路径,并添加依赖项在这里插入图片描述
    在这里插入图片描述

然后在项目中引用.h即可使用库中函数;要注意的是link若报错,则添加忽略项即可。
2 动态库:
首先项目属性设置为输出dll文件。
编写相应的.h和.cpp文件实现功能。
要注意指定导出的变量或函数,有以下方法:

#ifdef MYDLL_EXPORTS
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif 
//以上是将declspec用宏定义包装(别名),dllexport意思是被此宏修饰的变量或函数是要从dll中导出去的
//而dllimport的意思是要从别的dll中读取进来
//此方法不能有.def文件,一定不能有!
 
//导出类
class MYDLL_API Rectangle
{public:
    double getarea(double w, double h);
    void   print();
 
};
 
//导出函数,变量也一样可以导出
MYDLL_API int mysum(int a, int b);//注意是写在函数前面!
//一般都在.h中写好,但在.cpp中写也一样,注意只能有一处写,不然报错
//导出类若有了修饰,则它的成员函数不需要写这个修饰

还有就是编写.def文件,并加入到设置
在这里插入图片描述
内容如下:

LIBRARY MyDll(dll的名称,是真的dll的名称哦,引用dll时都用这个名称,若不用def则就是生成文件的名字)
EXPORTS
函数名1(如MyAdd)
函数2...

引用动态库:

//只需要Dll文件放在exe文件同一目录下即可
#include#includetypedef int(*Pmysum)(int a, int b);//定义一个指针函数类型
int main()
{HMODULE Hdll = LoadLibrary(L"Add.dll");//获取dll地址
    if (Hdll != NULL)
    {Pmysum mysunm = (Pmysum)GetProcAddress(Hdll, "Sub");//获取dll中的函数地址
        if (mysunm != NULL)
        {std::cout<< "调用两变量相加函数:"<< mysunm(7, 2);
        }
    }
    FreeLibrary(Hdll);//卸载dll
    return 0;
}

第二种方法是,将.h、.lib和.dll都放在某一目录中,在项目属性中,包含目录指定.h,附加库目录指定.lib,附加依赖项指定.lib,.dll放在exe同一目录下。

//若只指定包含目录.h,则用以下方法
#pragma comment(lib,"MyDll.lib) (此方法需要将该lib文件放到与exe同目录下)

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


网页题目:C++编译与链接-创新互联
地址分享:http://azwzsj.com/article/dgjdoj.html