#pragma directive
#pragma package(smart_init)
#pragma package(smart_init)确保已打包的单元按照其依赖关系确定的顺序进行初始化(默认情况下包含在package(包)源文件中。)通常,您将#pragma package用于作为package(包)构建的.cpp文件。简而言之就是按照单元的依赖关系顺序进行初始化,一般用于构建Package(软件包)中
注意:不要在头文件中使用#pragma package(smart_init)。 这样做可能导致编译器错误。
该编译指令影响该编译单元的初始化顺序。 对于单元,初始化按以下顺序进行:
1)根据它们的“uses”依赖性,即,如果unitA依赖于unitB,则必须在unitA之前初始化unitB。
2)链接顺序。
3)单元(unit)内的优先级顺序。
对于常规目标文件(obj文件)(不是作为单元(unit)构建的目标文件),首先根据优先级顺序进行初始化,然后根据链接顺序进行初始化。 更改对象文件的链接顺序将更改全局对象构造函数的调用顺序。
以下示例显示了单元和常规目标文件之间的初始化有何不同。
假设您有三个源文件A,B和C,它们使用#pragma package(smart_init)“智能初始化”,并且具有优先级设置为10、20和30的函数(由#pragma startup的优先级参数定义)。这些函数是根据其优先级值和父源文件命名的,因此名称分别为a10,a20,a30,b10,b20等。这是三个程序A,B和C:
// A.cpp
#include <stdio.h> #ifdef USE_PACKAGE_INIT
#pragma package(smart_init)
#endif void A10() {
printf("%s() ", __FUNCTION__);
}
#pragma startup A10 10 void A20() {
printf("%s() ", __FUNCTION__);
}
#pragma startup A20 20 void A30() {
printf("%s() ", __FUNCTION__);
}
#pragma startup A30 30
// B.cpp
#include <stdio.h> #ifdef USE_PACKAGE_INIT
#pragma package(smart_init)
#endif void B10() {
printf("%s() ", __FUNCTION__);
}
#pragma startup B10 10 void B20() {
printf("%s() ", __FUNCTION__);
}
#pragma startup B20 20 void B30() {
printf("%s() ", __FUNCTION__);
}
#pragma startup B30 30
// C.cpp
#include <stdio.h> #ifdef USE_PACKAGE_INIT
#pragma package(smart_init)
#endif void C10() {
printf("%s() ", __FUNCTION__);
}
#pragma startup C10 10 void C20() {
printf("%s() ", __FUNCTION__);
}
#pragma startup C20 20 void C30() {
printf("%s() ", __FUNCTION__);
}
#pragma startup C30 30
如果按编写的方式并定义了USE_PACKAGE_INIT来构建源文件,则会打印出以下内容:
> A10() A20() A30() B10() B20() B30() C10() C20() C30()
也就是说,优先级被忽略,每个单元一次运行其所有初始化。
如果您在未定义USE_PACKAGE_INIT的情况下构建源文件,则会得到完全不同的结果。 在这种情况下,运行程序时,将输出以下内容:
> A10() B10() C10() A20() B20() C20() A30() B30() C30()
也就是说,使用 startup优先级顺序。
由于这三个都是单元,并且如果A uses B和C,并且链接顺序是A,B,C,则初始化的顺序是:
> B10()B20()B30()C10()C20()C30() A10()A20()A30()
如果以上是目标文件,而不是单元,则顺序为:
> A10()B10()C10()A20()B20()C20()A30()B30()C30()
使用#pragma package(smart_init)的.cpp文件还要求从任意声明#pragma pragma(smart_init)的.cpp文件中到其他目标文件的任何#pragma link引用都必须由一个单元解析。仍然可以通过库解析对非对象文件的#pragma link引用,依此类推。
#pragma package(smart_init, weak)
#pragma package(smart_init,weak)指令会影响对象文件在包的.bpi和.bpl文件中的存储方式。 如果#pragma package(smart_init,weak)出现在单元文件中,则编译器将在可能的情况下从BPL中忽略该单元,并在另一个应用程序或程序包需要时创建该单元的未打包的本地副本。 使用此伪指令编译的单元被称为“弱包装”。
#pragma package(smart_init,weak)用于消除可能依赖于同一外部库的程序包之间的冲突。
包含#pragma package(smart_init,weak)指令的单元文件不得具有全局变量。
#pragma link
语法:
#pragma link "[path]modulename[.ext]"
#pragma link指令指示链接程序将指定文件链接到可执行文件中。
使用path参数指定目录。 缺省情况下,链接器在本地目录和链接器的-L选项指定的任何路径中搜索模块名称。
只要您使用默认文件类型,就不要指定modulename的文件扩展名(.ext)。 链接器为modulename的文件扩展名(.ext)假定以下默认值:
.objextension for BCC32.oextension for Clang-enhanced C++ compilers
因此,如果省略.ext,则会根据您当前的目标平台自动使用正确的扩展名。
#pragma directive的更多相关文章
- #pragma Directive in C/C++
The #pragma is complier specified. for example, the code below does not work in gcc. #pragma startup ...
- 重新梳理HTML基础知识
缘起 HTML(HyperText Markup Language超文本标记语言)是用于构建web页面的标记语言和通用标准.它并不是一项新的发明,因为超文本(具有超链接的文本)和标记语言(用于电子文档 ...
- C中的预编译宏定义
可以用宏判断是否为ARC环境 #if _has_feature(objc_arc) #else //MRC #endif C中的预编译宏定义 -- 作者: infobillows 来源:网络 在将一 ...
- How do I place a group of functions or variables in a specific section?
http://supp.iar.com/Support/?Note=27498 EWARM v5.xx (and newer) The placement of a few functions in ...
- RFC 2616
Network Working Group R. Fielding Request for Comments: 2616 UC Irvine Obsoletes: 2068 J. Gettys Cat ...
- 基于NodeJs的网页爬虫的构建(一)
好久没写博客了,这段时间已经忙成狗,半年时间就这么没了,必须得做一下总结否则白忙.接下去可能会有一系列的总结,都是关于定向爬虫(干了好几个月后才知道这个名词)的构建方法,实现平台是Node.JS. 背 ...
- scanf()常犯错误
------------------------------------------------------------------------ <> 本意:接收字符串. 写成代码:voi ...
- RFC2616-HTTP1.1-Header Field Definitions(头字段规定部分—单词注释版)
part of Hypertext Transfer Protocol -- HTTP/1.1RFC 2616 Fielding, et al. 14 Header Field Definitions ...
- HTML5 Differences from HTML4
Abstract "HTML5 Differences from HTML4" describes the differences of the HTML5 specificati ...
- C预编译, 预处理, C/C++头文件, 编译控制,
在所有的预处理指令中,#Pragma 指令可能是最复杂的了,它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作.#pragma指令对每个编译器给出了一个方法,在保持与C和C++语言完全兼容的 ...
随机推荐
- php7.3的安装以及在Apache中部署php
安装 php7.3 1.进入php官网:https://www.php.net/downloads.php 2.点击 Windows downloads 3.下载压缩包 4.将下载好的压缩包解压,可选 ...
- RESTful相关信息整理
RESTful相关信息整理 参考:可以看的出来我是阮一峰的忠实读者 阮一峰的<理解RESTful架构> https://www.ruanyifeng.com/blog/2011/09/re ...
- ChatGpt国内教程
近ChatGPT大火呀,小伙伴们是不是在网上看到各种和ChatGPT有趣聊天的截图,比如翻译代码.编写代码,奈何自己实力不够,被网络拒之门外,只能眼馋别人的东西.看别人玩,肯定不如自己玩一把舒服的啊. ...
- linux 基础(7)账号和群组的管理
了解账号和群组的基本信息 账号使用 如何查看 linux 计算机上有哪些账号呢?账号的信息储存在/etc/passwd中,打开就可以看到: less /etc/passwd root:x:0:0:ro ...
- 栈——stack的用法
介绍 栈(stack)又名堆栈,它是一种运算受限的线性表.限定仅在表尾进行插入和删除操作的线性表.这一端被称为栈顶,相对地,把另一端称为栈底.向一个栈插入新元素又称作进栈.入栈或压栈,它是把新元素放到 ...
- Zstack使用经验系列2-安装的存储配置
从上图读者应该能看出当初分配主存储和镜像存储时空间分配的是多么不合理,镜像空间不需要那么多.不过这时系统已经运行了近1年,很多云主机以及系统服务都搭好了,如果再重新分配空间是多么的麻烦! 所以开始为p ...
- 安卓逆向 ARM基础篇 二
1.寄存器寻址的八中方法 1.立即寻址 二 寄存器寻址 三 寄存器移位寻址 过程 R2 移位 传给R0 四 寄存器间接寻址 五 基址寻址 六 多寄存器寻址 七 堆栈寻址 七 堆栈寻址
- 利用canvas+js完成滑块验证码中canvas部分思路
1. 最终效果 2.滑块验证码思路 大概思路:设置两个画布,一个为显示图像的canvas画布,一个为拼图的block画布,block画布拼图内容从图像画布中的一部分裁剪得到(使用clip()),通过绑 ...
- P3387 缩点
\(Tarjan\) 模板 #include<cstdio> #include<queue> #include<iostream> #define re regis ...
- C#泛型接口请求封装类
using HttpUtil; using Newtonsoft.Json; using System; using System.Collections.Generic; using System. ...