| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> C++知识库 -> 【C语言基础】GNU C 关键字__attribute__用法 -> 正文阅读 |
|
[C++知识库]【C语言基础】GNU C 关键字__attribute__用法 |
__ attribute __是GNU C 编译器用于声明函数、变量或类型属性的关键字。 __ attrabute __ 的用法:在被定义的函数、变量或者类型名前/后按如下方式添加属性即可:
注意: 属性(ATTRIBUTE)有十几种,常用的有以下几种: 对一个变量可以添加一个或多个属性。
section属性可执行文件主要由代码段,数据段、BSS 段构成,还可以包含一些其他自定义段。 section 属性作用:编译时,将一个函数或者变量放到指定的段 使用 __ attribute __ ((section(“xxx”))),修改段的属性
对齐属性GNU C 通过 attribute 声明 变量或类型的对齐方式的属性有两种: aligned 属性显式指定变量或类型在内存中的地址对齐方式
思考:为啥需要指定地址对齐方式呢? 结构体对齐结构体作为一种复杂的数据类型,编译器在给一个结构体变量分配存储空间时,不仅要考虑结构体内各个成员的对齐,还要考虑结构体整体的对齐。为了结构体各成员对齐,编译器可能会在结构体内填充一些字节。为了结构体的整体对齐,编译器可能会在结构体的末尾一些空间。 结构体成员顺序不同,所占大小有可能不同:
四字节对齐:占12字节
显式的指定成员的对齐方式:
四字节对齐:占12字节 显式的指定结构体对齐方式:
16字节对齐,末尾填充8字节:占16字节 编译器一定会按照 aligend 指定的方式对齐吗?aligend属性声明,其实只是建议编译器按照这种大小地址对齐,但是不能超过编译器允许的最大值。编译器对每个基本的数据类型都有默认的最大边界对齐字节数,如果超过了,则编译器只能按照它规定的最大对齐字节数来对变量分配地址。 packed 属性aligned 对齐一般会增大变量的地址,变量或结构体成员变量之间地址对齐可能会造成一定的内存空洞(内存空间浪费),而packed对齐则正好相反,一般用来减少变量间的空洞,使变量间紧挨着,指定变量或类型使用最可能小的地址对齐方式。 使用packed属性显式的声明结构体成员
使用最小一字节对齐 使用packed属性显式的声明整个结构体
内核中的packed、aligned 声明在内核源码中,我们经常看到aligned 和 packed 一起使用,即对一个变量或者类型同时使用packed 和 aligned 属性声明。这样做的好处是即避免了结构体各成员间地址对齐产生的内存空洞,又指定了整个结构体的对齐方式。
format属性format 属性用来指定变参函数的参数格式检查。
示例:
属性format(printf,1,2) 有3个参数, weak属性GNU C 通过 weak 属性声明,将一个强符号,转换为弱符号。
以编译器视角看,变量名/函数名仅仅是个符号而已,符号分为强符号和弱符号。 一个工程中如果同时存在两个强符号,那么链接器在链接时就会报重定义错误。 一个工程中允许强符号和弱符号同时存在,比如可以定义一个初始化的全局变量和一个未初始化的全局变量,这种写法在编译时是可以编过的。 一个工程中存在多个弱符号时,那么编译器该选择哪个呢?谁在内存中存储空间大,就选谁。 结论: 弱符号的用途在一个源文件中引用一个编号或者函数,当编译器只看到声明,而没看到其定义时,一般编译时不会报错。在链接阶段,链接器会到其他文件中找到这些符号的定义,若未找到,则报未定义错误。 当函数被声明一个弱符号时,会有一个奇特地方:当链接器找不到这个函数的定义时,也不会报错。编译器会将这个函数名,即弱符号,设置为0或者一个特殊值。只有当程序运行时,调用到这个函数,跳转到零地址或者一个特殊的地址才会报错误,产生一个内存错误。 如果我们在使用函数前,判断这个函数地址是否为0,即可避免段错误。你会发现,即使函数未定义也可以正常编过。 弱符号的这个特性在库函数开发设计中应用十分广泛,如果在开发一个库时,基础功能已经实现,有些高级功能还未实现,那么你就可以将这些函数通过weak 属性声明转换为一个弱符号。 alias属性alias 属性主要用来给函数定义一个别名 示例
在Linux 内核中你会发现alias有时候会和weak属性一起使用。如有些接口随着内核版本升级,函数接口发生了变化,我们可以通过alias属性对旧的接口名字进行封装,重新起一个接口名字。
如果main.c 中定义了f()函数,那么main 函数调用f()会调用新定义的函数(强符号),否则调用__f()函数(弱符号) noinline 和 always_inline属性内联函数说起内联函数,就不得不说起函数调用开销。 内联函数与宏与宏相比,内联函数有以下优势: 编译器对内联函数的处理编译器不一定会展开内联函数,编译器根据实际情况进行评估,权衡展开和不展开的利弊,并最终决定要不要展开。 内联函数缺点: 满足以下几点的函数适合被声明为内联函数: 函数使用 noinline 或 always_inline 属性声明的形式如下:
内联函数为什么定义在头文件中?在Linux 内核中,存在大量的内联函数被定义在头文件中,而且常常使用static关键字修饰。 为什么定义在头文件中呢? 为什么还要用static 修饰呢? 参考wiki: |
|
C++知识库 最新文章 |
【C++】友元、嵌套类、异常、RTTI、类型转换 |
通讯录的思路与实现(C语言) |
C++PrimerPlus 第七章 函数-C++的编程模块( |
Problem C: 算法9-9~9-12:平衡二叉树的基本 |
MSVC C++ UTF-8编程 |
C++进阶 多态原理 |
简单string类c++实现 |
我的年度总结 |
【C语言】以深厚地基筑伟岸高楼-基础篇(六 |
c语言常见错误合集 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 | -2025/1/11 12:39:42- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |