QT源码学习 | 编译器知识点

简介: 本文是关于QT源码学习中编译器知识点的总结,包括`__declspec`、`Q_FUNC_INFO`、`__assume`、`__attribute__`、`__ASSEMBLER__`、`QT_SUPPORTS`和`QT_WARNING_DISABLE_MSVC`等宏定义的使用和作用,以及相关参考链接。

一 知识点来源

C:\Qt\5.15.2\msvc2019_64\include\QtCore\qcompilerdetection.h

C:\Qt\5.15.2\msvc2019_64\include\QtCore\qglobal.h

二 知识点

1 __declspec

__declspec用于指定所给定类型的实例的与Microsoft相关的存储方式。其它的有关存储方式的修饰符如static与extern等是C和 C++语言的ANSI规范,而__declspec是一种扩展属性的定义。扩展属性语法简化并标准化了C和C++语言关于Microsoft的扩展。

1.__declspec关键字应该出现在简单声明的前面。对于出现在*或&后面或者变量声明中标识符的前面的__declspec,编译器将忽略并且不给出警告。
2.要注意区分__declspec是修饰类型还是修饰变量:
__declspec(align(8)) struct Str b;修饰的是变量b。其它地方定义的struct Str类型的变量将不受__declspec(align(8))影响。
__declspec(align(8)) struct Str {};修饰的是struct Str类型。所有该类型的变量都受__declspec(align(8))影响。

dllimport,dllexport
格式:
__declspec( dllimport ) declarator
__declspec( dllexport ) declarator
分别用来从dll导入函数,数据,或对象以及从dll中导出函数,数据,或对象。相当于定义了dll的接口,为它的客户exe或dll定义可使用的函数,数据,或对象。
将函数声明成dllexport就可以免去定义模块定义(.DEF)文件。
dllexport代替了__export关键字。
被声明为dllexport的C++函数导出时的函数名将会按照C++规则经过处理。如果要求不按照C++规则进行名字处理,请使用.def文件或使用extern "C"。

noreturn
一个函数被__declspec(noreturn)所修饰,那么它的含义是告诉编译器,这个函数不会返回,其结果是让编译器知道被修饰为__declspec(noreturn)的函数之后的代码不可到达。
如果编译器发现一个函数有无返回值的代码分支,编译器将会报C4715警告,或者C2202错误信息。如果这个代码分支是因为函数不会返回从而无法到达的话,可以使用约定__declspec(noreturn)来避免上述警告或者错误。
将一个期望返回的函数约定为__declspec(noreturn)将导致未定义的行为。
在下面的这个例子中,main函数没有从else分支返回,所以约定函数fatal为__declspec(noreturn)来避免编译或警告信息。
__declspec(noreturn) extern void fatal () {}
int main() {
if(1)
return 1;
else if(0)
return 0;
else
fatal();
}

/* Symantec C++ is now Digital Mars */
#if defined(__DMC__) || defined(__SC__)
#  define Q_CC_SYM
/* "explicit" semantics implemented in 8.1e but keyword recognized since 7.5 */
#  if defined(__SC__) && __SC__ < 0x750
#    error "Compiler not supported"
#  endif

#elif defined(_MSC_VER)
#  ifdef __clang__
#    define Q_CC_CLANG ((__clang_major__ * 100) + __clang_minor__)
#  endif
#  define Q_CC_MSVC (_MSC_VER)
#  define Q_CC_MSVC_NET
#  define Q_OUTOFLINE_TEMPLATE inline
#  define Q_COMPILER_MANGLES_RETURN_TYPE
#  define Q_FUNC_INFO __FUNCSIG__
#  define Q_ALIGNOF(type) __alignof(type)
#  define Q_DECL_ALIGN(n) __declspec(align(n))
#  define Q_ASSUME_IMPL(expr) __assume(expr)
#  define Q_UNREACHABLE_IMPL() __assume(0)
#  define Q_NORETURN __declspec(noreturn)
#  define Q_DECL_DEPRECATED __declspec(deprecated)
#  ifndef Q_CC_CLANG
#    define Q_DECL_DEPRECATED_X(text) __declspec(deprecated(text))
#  endif
#  define Q_DECL_EXPORT __declspec(dllexport)
#  define Q_DECL_IMPORT __declspec(dllimport)
#  define QT_MAKE_UNCHECKED_ARRAY_ITERATOR(x) stdext::make_unchecked_array_iterator(x) // Since _MSC_VER >= 1800
#  define QT_MAKE_CHECKED_ARRAY_ITERATOR(x, N) stdext::make_checked_array_iterator(x, size_t(N)) // Since _MSC_VER >= 1500
/* Intel C++ disguising as Visual C++: the `using' keyword avoids warnings */
#  if defined(__INTEL_COMPILER)
#    define Q_DECL_VARIABLE_DEPRECATED
#    define Q_CC_INTEL  __INTEL_COMPILER
#  endif

2 # define Q_FUNC_INFO __FUNCSIG__

__FUNCTION__ 特性最初是为C语言设计的,然而,C++程序员也会经常需要有关他们函数的额外信息,在Visual Studio 2005中,还支持另外两种非标准的扩展特性:__FUNCDNAME__ 与 __FUNCSIG__ ,其分别转译为一个函数的修饰名与签名。

例子
int test(int x)
vs2010
__FUNCTION__:test
__FUNCDNAME__:?test@@YAHH@Z
__FUNCSIG__:int __cdecl test(int)
gcc
__FUNCTION__:test
__func__:test

3 __assume

Microsoft 专用

传递优化程序提示。

#  define Q_ASSUME_IMPL(expr) __assume(expr)
#  define Q_UNREACHABLE_IMPL() __assume(0)
// compiler_intrinsics__assume.cpp
#ifdef DEBUG
# define ASSERT(e)    ( ((e) || assert(__FILE__, __LINE__) )
#else
# define ASSERT(e)    ( __assume(e) )
#endif

void func1(int i)
{
   
}

int main(int p)
{
   
   switch(p){
   
      case 1:
         func1(1);
         break;
      case 2:
         func1(-1);
         break;
      default:
         __assume(0);
            // This tells the optimizer that the default
            // cannot be reached. As so, it does not have to generate
            // the extra code to check that 'p' has a value
            // not represented by a case arm. This makes the switch
            // run faster.
   }
}

4 __attribute__

GNU C 的一大特色就是__attribute__ 机制。__attribute__ 可以设置函数属性(Function Attribute )、变量属性(Variable Attribute )和类型属性(Type Attribute )。

__attribute__ 书写特征是:__attribute__ 前后都有两个下划线,并切后面会紧跟一对原括弧,括弧里面是相应的__attribute__ 参数。

__attribute__ 语法格式为:__attribute__ ((attribute-list))

关键字__attribute__ 也可以对结构体(struct )或共用体(union )进行属性设置。大致有六个参数值可以被设定,即:aligned, packed, transparent_union, unused, deprecated 和 may_alias 。

在使用__attribute__ 参数时,你也可以在参数的前后都加上“__” (两个下划线),例如,使用__aligned__而不是aligned ,这样,你就可以在相应的头文件里使用它而不用关心头文件里是否有重名的宏定义。

在TC下:struct my{
    char ch; int a;}      sizeof(int)=2;sizeof(my)=3;(紧凑模式)

在GCC下:struct my{
    char ch; int a;}     sizeof(int)=4;sizeof(my)=8;(非紧凑模式)

在GCC下:struct my{
    char ch; int a;}__attrubte__ ((packed))        sizeof(int)=4;sizeof(my)=5

5 __ASSEMBLER__

#ifndef __ASSEMBLER__
#  include <assert.h>
#  include <stddef.h>
#endif

当预处理汇编语言,置为1

6 # define QT_SUPPORTS(FEATURE) (!defined QT_NO_##FEATURE)

define 中的# ## 一般是用来拼接字符串的,但是实际使用过程中,有哪些细微的差别呢,我们通过几个例子来看看。

是字符串化的意思,出现在宏定义中的#是把跟在后面的参数转成一个字符串;

eg:

define strcpy__(dst, src) strcpy(dst, #src)

strcpy__(buff,abc) 相当于 strcpy__(buff,“abc”)

是连接符号,把参数连接在一起

define FUN(arg) my##arg

则 FUN(ABC)

等价于 myABC

7 # define QT_WARNING_DISABLE_MSVC(number) __pragma(warning(disable: number))

下面的注释很搞笑,stupid compilers


/*
   Avoid some particularly useless warnings from some stupid compilers.
   To get ALL C++ compiler warnings, define QT_CC_WARNINGS or comment out
   the line "#define QT_NO_WARNINGS".
*/
#if !defined(QT_CC_WARNINGS)
#  define QT_NO_WARNINGS
#endif
#if defined(QT_NO_WARNINGS)
#  if defined(Q_CC_MSVC)
QT_WARNING_DISABLE_MSVC(4251) /* class 'type' needs to have dll-interface to be used by clients of class 'type2' */
QT_WARNING_DISABLE_MSVC(4244) /* conversion from 'type1' to 'type2', possible loss of data */
QT_WARNING_DISABLE_MSVC(4275) /* non - DLL-interface classkey 'identifier' used as base for DLL-interface classkey 'identifier' */
QT_WARNING_DISABLE_MSVC(4514) /* unreferenced inline function has been removed */
QT_WARNING_DISABLE_MSVC(4800) /* 'type' : forcing value to bool 'true' or 'false' (performance warning) */
QT_WARNING_DISABLE_MSVC(4097) /* typedef-name 'identifier1' used as synonym for class-name 'identifier2' */
QT_WARNING_DISABLE_MSVC(4706) /* assignment within conditional expression */
QT_WARNING_DISABLE_MSVC(4355) /* 'this' : used in base member initializer list */
QT_WARNING_DISABLE_MSVC(4710) /* function not inlined */
QT_WARNING_DISABLE_MSVC(4530) /* C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc */
#  elif defined(Q_CC_BOR)
#    pragma option -w-inl
#    pragma option -w-aus
#    pragma warn -inl
#    pragma warn -pia
#    pragma warn -ccc
#    pragma warn -rch
#    pragma warn -sig
#  endif
#endif

编译器还支持特定于 __pragma Microsoft 的关键字,该关键字的功能与 #pragma 指令相同。 区别在于, __pragma 关键字在宏定义中可内联使用。 指令 #pragma 在宏定义中不可用,因为编译器将指令中的数字符号字符 ('#') 解释为 字符串化运算符 (#)

三 参考链接

(4条消息) __declspec用法详解_章志强的博客-CSDN博客___declspec

(4条消息) __declspec(dllexport)和__declspec(dllimport)_pinganyehandan的博客-CSDN博客

__FUNCSIG__ __FUNCDNAME__ __FUNCTION__ __func__ - 八叶草 - C++博客 (cppblog.com)

Clang Language Extensions — Clang 15.0.0git documentation (llvm.org)

SD-FeatureTest: Feature-Test Macros and Policies : Standard C++ (isocpp.org)

__assume | Microsoft Docs

(4条消息) C语言__attribute__的使用_【ql君】qlexcel的博客-CSDN博客___attribute__

宏定义 - 知乎 (zhihu.com)

C++/C 宏定义(define)中# ## 的含义 宏拼接 - sz123 - 博客园 (cnblogs.com)

Pragma 指令和 __pragma 和 _Pragma 关键字 | Microsoft Docs

相关文章
|
11天前
|
弹性计算 人工智能 架构师
阿里云携手Altair共拓云上工业仿真新机遇
2024年9月12日,「2024 Altair 技术大会杭州站」成功召开,阿里云弹性计算产品运营与生态负责人何川,与Altair中国技术总监赵阳在会上联合发布了最新的“云上CAE一体机”。
阿里云携手Altair共拓云上工业仿真新机遇
|
8天前
|
机器学习/深度学习 算法 大数据
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析
2024“华为杯”数学建模竞赛,对ABCDEF每个题进行详细的分析,涵盖风电场功率优化、WLAN网络吞吐量、磁性元件损耗建模、地理环境问题、高速公路应急车道启用和X射线脉冲星建模等多领域问题,解析了问题类型、专业和技能的需要。
2522 17
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析
|
8天前
|
机器学习/深度学习 算法 数据可视化
【BetterBench博士】2024年中国研究生数学建模竞赛 C题:数据驱动下磁性元件的磁芯损耗建模 问题分析、数学模型、python 代码
2024年中国研究生数学建模竞赛C题聚焦磁性元件磁芯损耗建模。题目背景介绍了电能变换技术的发展与应用,强调磁性元件在功率变换器中的重要性。磁芯损耗受多种因素影响,现有模型难以精确预测。题目要求通过数据分析建立高精度磁芯损耗模型。具体任务包括励磁波形分类、修正斯坦麦茨方程、分析影响因素、构建预测模型及优化设计条件。涉及数据预处理、特征提取、机器学习及优化算法等技术。适合电气、材料、计算机等多个专业学生参与。
1525 15
【BetterBench博士】2024年中国研究生数学建模竞赛 C题:数据驱动下磁性元件的磁芯损耗建模 问题分析、数学模型、python 代码
|
4天前
|
存储 关系型数据库 分布式数据库
GraphRAG:基于PolarDB+通义千问+LangChain的知识图谱+大模型最佳实践
本文介绍了如何使用PolarDB、通义千问和LangChain搭建GraphRAG系统,结合知识图谱和向量检索提升问答质量。通过实例展示了单独使用向量检索和图检索的局限性,并通过图+向量联合搜索增强了问答准确性。PolarDB支持AGE图引擎和pgvector插件,实现图数据和向量数据的统一存储与检索,提升了RAG系统的性能和效果。
|
10天前
|
编解码 JSON 自然语言处理
通义千问重磅开源Qwen2.5,性能超越Llama
击败Meta,阿里Qwen2.5再登全球开源大模型王座
584 14
|
1月前
|
运维 Cloud Native Devops
一线实战:运维人少,我们从 0 到 1 实践 DevOps 和云原生
上海经证科技有限公司为有效推进软件项目管理和开发工作,选择了阿里云云效作为 DevOps 解决方案。通过云效,实现了从 0 开始,到现在近百个微服务、数百条流水线与应用交付的全面覆盖,有效支撑了敏捷开发流程。
19283 30
|
10天前
|
人工智能 自动驾驶 机器人
吴泳铭:AI最大的想象力不在手机屏幕,而是改变物理世界
过去22个月,AI发展速度超过任何历史时期,但我们依然还处于AGI变革的早期。生成式AI最大的想象力,绝不是在手机屏幕上做一两个新的超级app,而是接管数字世界,改变物理世界。
489 49
吴泳铭:AI最大的想象力不在手机屏幕,而是改变物理世界
|
1月前
|
人工智能 自然语言处理 搜索推荐
阿里云Elasticsearch AI搜索实践
本文介绍了阿里云 Elasticsearch 在AI 搜索方面的技术实践与探索。
18842 20
|
1月前
|
Rust Apache 对象存储
Apache Paimon V0.9最新进展
Apache Paimon V0.9 版本即将发布,此版本带来了多项新特性并解决了关键挑战。Paimon自2022年从Flink社区诞生以来迅速成长,已成为Apache顶级项目,并广泛应用于阿里集团内外的多家企业。
17530 13
Apache Paimon V0.9最新进展
|
2天前
|
云安全 存储 运维
叮咚!您有一份六大必做安全操作清单,请查收
云安全态势管理(CSPM)开启免费试用
367 4
叮咚!您有一份六大必做安全操作清单,请查收