c语言attribute关键字参数(详细)总结附示例快速掌握

news2024/11/17 16:04:28

目录

    • 一、简介
    • 二、参数详解
      • 2.1 section:自定义段
      • 2.2 aligned:对齐
      • 2.3 packed:对齐
      • 2.4 format:检查函数变参格式
      • 2.5 used
      • 2.6 unused
      • 2.7 at 绝对定位
      • 2.8 constructor
      • 2.9 destructor
      • 2.10 weak:弱声明
      • 2.11 alias:函数起别名
      • 2.12 always_inline:内联函数总是展开
      • 2.13 noinline:无内联
      • 2.14 transparent_union
      • 2.15 deprecated
      • 2.16 noreturn
    • 三、其他相关链接

一、简介

GNU C编译器增加了一个__attribute__ 关键字用来声明一个函数、变量或类型的特殊属性。申明这些属性主要用途就是指导编译程序进行特定方面的优化或代码检查。
attribute 可以设置函数属性(Function Attribute )、变量属性(Variable Attribute )和类型属性(Type Attribute )。
关键字__attribute__ 也可以对结构体(struct )或共用体(union )进行属性设置。
attribute 书写特征是:attribute 前后都有两个下划线,并切后面会紧跟一对原括弧,括弧里面是相应的__attribute__ 参数,格式如下:

 __attribute__ ((ATTRIBUTE))

二、参数详解

2.1 section:自定义段

section属性的主要作用是:在程序编译时,将一个函数或者变量放到指定的段,即指定的section中。
一个可执行文件注意由代码段,数据段、bss段构成。代码段主要用来存放编译生成的可执行指令代码、数据段和bss段用来存放全局变量和未初始化的全局变量。
除了这三个段,可执行文件还包含一些其他的段。我们可以用 readelf 去查看一个可执行文件各个section信息。

int global_val = 0;
int unint_val __attribute__((section(".data")));

int main()
{
    return 0;
}

在这里插入图片描述

2.2 aligned:对齐

GNU C 通过 __attribute__ 来声明 aligned 和 packed 属性,指定一个变量或类型的对齐方式。

通过aligned属性,我们可以显示地指定变量在内存中的地址对齐方式。aligned有一个参数,表示要按几个字节对齐,使用时要注意,地址对齐的字节数必须是 2 的幂次方,否则编译就会报错。

在这里插入图片描述

2.3 packed:对齐

在这里插入图片描述aligned 属性一般用来增大变量的地址对齐,元素之间地址对齐会造成一定的内存空洞,而packed属性则正好相反,一般用来减少地址对齐,指定变量或类型使用最可能小的地址对齐方式。

2.4 format:检查函数变参格式

指定变参函数的参数格式检查

__attribute__((format (archetype, string-index, frist-to-check)))
void LOG(const char *fmt, ...) __attribute__((format(printf,1,2)));

属性format(printf,1,2) 有3个参数,第一个参数pritnf 是告诉编译器,按照printf的标准来检查;第二个参数表示LOG()函数所有的参数列表中格式字符串的位置索引,第三个参数是告诉编译器要检查的参数的起始位置。

LOG("hello world ,i am %d ages ", age); /* 前者表示格式字符串,后者表示所有的参数*/

2.5 used

used的作用是告诉编译器,我声明的这个符号是需要保留的。被used修饰以后,意味着即使函数没有被引用,在Release下也不会被优化。如果不加这个修饰,那么Release环境链接器会去掉没有被引用的段。
1、这个函数属性通知编译器在目标文件中保留一个静态函数,即使它没有被引用;
2、标记为attribute__((used))的函数被标记在目标文件中,以避免链接器删除未使用的节;
3、静态变量也可以标记为used,方法是使用 attribute((used))。

static int lose_this(int);
static int keep_this(int) __attribute__((used));     // retained in object file

__attribute__((used,section(".rodata.$AppID")))
const uint8_t   ApplicationID[16] = {
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x12, 0x34, 0x00, 0x00
};

2.6 unused

表示该函数或变量可能不使用,这个属性可以避免编译器产生警告信息。

#define __attribute_unused__ __attribute__((__unused__))

2.7 at 绝对定位

绝对定位,可以把变量或函数绝对定位到Flash中,或者定位到RAM。
定位到flash中,一般用于固化的信息,如出厂设置的参数,上位机配置的参数,ID卡的ID号,flash标记等等。

const u16 gFlashDefValue[512] __attribute__((at(0x0800F000))) = {0x1111,0x1111,0x1111,0x0111,0x0111,0x0111};//定位在flash中,其他flash补充为00
const u16 gflashdata__attribute__((at(0x0800F000))) = 0xFFFF;

2.8 constructor

确保此函数在main函数被调用之前调用
constructor和destructor会在ELF文件中添加两个段-.ctors和.dtors。当动态库或程序在加载时,会检查是否存在这两个段,如果存在执行对应的代码。

int main(int argc, char * argv[]) {
    @autoreleasepool {
        printf("main function");
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}
__attribute__((constructor)) static void beforeFunction()
{
    printf("beforeFunction\n");
}

打印结果如下:

beforeFunction
main function
static  __attribute__((constructor(101))) void before1()
{
        printf("before1\n");
}
static  __attribute__((constructor(102))) void before2()
{
        printf("before2\n");
}
static  __attribute__((constructor(102))) void before3()
{
        printf("before3\n");
}

以上三个函数会依照优先级的顺序调用.另外,我以前看过,这个1-100的范围是保留的,所以,最好从100之后开始用。

2.9 destructor

确保此函数在main()函数退出或者调用了exit()之后,调用我们的函数。

2.10 weak:弱声明

将一个强符号,转换为弱符号。使用方法如下:

void __attribute__((weak)) func(void);
int num __attribute__((weak));

在一个程序中,无论是变量名,还是函数名,在编译器眼里,就是一个符号而已,符号可以分为强符号和弱符号。
强符号:函数名,初始化的全局变量名
弱符号:未初始化的全局变量名。

//func1.c
int a __attribute__((weak)) = 1;
void func(void)
{
    printf("func.a = %d\n", a);
}

//main.c
int a = 4;
void __attribute__((weak)) func(void)
{
    printf("main.a = %d\n", a);
}

int main(void)
{
   func();
   return 0;
}

弱符号的用途
1、在一个源文件中引用一个编号或者函数,当编译器只看到声明,而没看到其定义时,一般编译时不会报错。在链接阶段,链接器会到其他文件中找到这些符号的定义,若未找到,则报未定义错误。

2、当函数被声明一个弱符号时,会有一个奇特地方:当链接器找不到这个函数的定义时,也不会报错。编译器会将这个函数名,即弱符号,设置为0或者一个特殊值。只有当程序运行时,调用到这个函数,跳转到零地址或者一个特殊的地址才会报错误,产生一个内存错误。

3、如果我们在使用函数前,判断这个函数地址是否为0,即可避免段错误。你会发现,即使函数未定义也可以正常编过。

4、弱符号的这个特性在库函数开发设计中应用十分广泛,如果在开发一个库时,基础功能已经实现,有些高级功能还未实现,那么你就可以将这些函数通过weak 属性声明转换为一个弱符号。

符号(或弱定义) weak属性只会在静态库(.o .a )中生效,动态库(.so)中不会生效

__attribute__((weakref(“别名”)))

//引用,必须是static类型,别名要写,不然等效于weak(其实也可以直接写成weak的形式)

2.11 alias:函数起别名

主要用来给函数定义一个别名

void __f(void)
{
    printf("__f\n");
}

void f(void) __attribute__((alias("__f")));
int main(void)
{
    f();
    return 0;
}

2.12 always_inline:内联函数总是展开

说起内联函数,就不得不说起函数调用开销。一个函数在执行过程中,如果要调用其他函数,则一般会执行以下过程:
1、保存当前函数现场;
2、跳到调用函数执行;
3、恢复当前函数现场;
4、继续执行当前函数;
对于一些短小精悍,并且调用频繁的函数,调用开销大,这个时候我们可以将函数声明为内联函数。编译器遇到内联函数会想宏一样将内联函数之间在调用处展开,这样做就减少了函数调用的开销。
当我们认为一个函数体积小、而且被大量调用,应做内联展开时,就可以使用static inline 关键字修饰它,但是编译器不一定会内联展开。如果想明确告诉编译器一定要展开,或者不展开就可以使用 noinline 和 always_inline 对函数的属性做一个声明。
内联的本质是用代码块直接替换掉函数调用处,好处是:快代码的执行,减少系统开销。

void test(int a)__attribute__((always_inline));

2.13 noinline:无内联

与always_inline相反,无内联展开

2.14 transparent_union

我们可以使用透明联合类型,函数指针能够指向参数类型不同的函数。

2.15 deprecated

如果被变量或者函数的声明使用deprecated属性进行描述,那么编译器编译过程中不会产生警告或者错误,但是,被该属性描述的变量或者函数在其他地方被调用,那么编译会产生警告,警告信息中包含过时接口定义的位置及代码中的引用位置。

#define attribute_deprecated __attribute__((deprecated))
/* Variable Attribute */
attribute_deprecated int  variable_old = 0;
/* Function Attribute */
attribute_deprecated void function_old(void);

2.16 noreturn

几个标注库函数,例如abort exit,没有返回值。GCC能够自动识别这种情况。noreturn属性指定像这样的任何不需要返回值的函数。当遇到类似函数还未运行到return语句就需要退出来的情况,该属性可以避免出现错误信息。

三、其他相关链接

1、C语言常用函数详细总结

2、C语言中指针、数组作为作为函数参数使用总结

3、C语言常见数据类型字节数和打印格式总结

4、C语言、Makefile和shell中添加打印调试信息总结

5、c语言volatile关键字总结

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/173201.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

macOS spotlight 聚焦 搜索范围自定义

文章目录Intro禁用不需要的查找范围,减少 spotlight 工作量/资源损耗搜索结果中的每个分类各自代表什么?Intro MBA升级系统之后,第一次充满电用了12h,之后的使用过程中掉电也很快。 新版本信息:macOS Ventura 13.1 (2…

I.MX6ULL裸机开发笔记1:启动方式

目录 启动模式设置步骤 1、三大模式 2.选择内部介质 3.选择接口编号 4.介质属性 原理图 芯片手册截图 开机相关全部引脚 启动设置表 启动模式设置步骤 1、三大模式 熔丝模式:烧录一次,发布产品外部模式:USB、串口等内部&#xff1a…

Windows系统下利用Anaconda搭建MXNet框架

1、mxnet MXNet 是一个深度学习库,类似于Theano 和 TensorFlow。最近想搞下深度学习,于是便安装mxnet。之前安装过TensorFlow,也踩了很多坑,可谓是历经波折。有的时候,配置环境真的是一门玄学。 2、关于网上的一些教…

手把手教你学习单片机-硬件基础知识

去耦电容的应用 C16 和 C19 起到的作 用是一样的,C10 的作用和他们两个不一样。 容值比较大的电容,理论上可以理解成水缸或者水池子,同时,大家可以直接把电流理 解成水流。 作用一,缓冲作用。当上电的瞬间,电流从电源处流下来的时候,不稳定,容易冲击电 子器件,加个…

基于云的文档管理系统——随时随地办公

如果您正在建立现代数字业务,您需要灵活地移动和分配您的劳动力。 DocuWare 移动劳动力解决方案可帮助您构建新的生产力模式:随时随地、任何设备。 毫不费力地捕捉、即时访问、始终安全 DocuWare 文档管理和工作流程自动化意味着当前流程的业务信息。 访…

【shell教程】| 简介及基本使用案例

文章目录一、简介二、脚本1 格式2 执行方式3 变量自定义变量特殊变量4 运算符5 条件判断6 流程控制1 if判断2 case语句3 for循环4 while 循环七、read读取控制台输入八、函数1 basename2 dirname3 自定义函数九、正则表达式十、文本处理工具1 cut2 grep3 sed4 awk一、简介 常见…

在线支付系列【1】支付演变史

有道无术,术尚可求,有术无道,止于术。 文章目录支付货币发展史物物交换实物货币纸质货币电子货币数字货币支付模式演变一方支付(现金当面支付)二方支付(商家银行)第三方支付(商家、银…

【GD32F427开发板试用】工业级串口OTA实现----移植韦东山老师BootLoader项目

本篇文章来自极术社区与兆易创新组织的GD32F427开发板评测活动,更多开发板试用活动请关注极术社区网站。作者:足球之路 一、综述 一款完善的工业产品往往需要支持在线更新程序的需求,业界最近火热的叫法叫做“OTA”。这篇文章记录我利用技术…

2001-2020年中国区域创新能力总、分指标效用值

中国区域创新能力总、分指标效用值2001-2020 1、时间:2001-2020年 2、范围:全国31个省份 3、来源:中国区域创新能力评价BG 4、指标包括: 区域创新能力综合效用值、知识创造效用值、知识获取效用值、企业创新效用值、创新环境…

《Composing Programs》(SICP python版) chap1 笔记(2)

《Composing Programs》(SICP python版) chap1 笔记(2) 文章目录《Composing Programs》(SICP python版) chap1 笔记(2)Chapter 1: Building Abstractions with Functions1.3 Defining New Functions1.3.1 EnvironmentsFunction Signatures(看语境翻译为函数原型比较…

【论文翻译】ViTPose: Simple Vision Transformer Baselines for Human Pose Estimation

【论文】https://arxiv.org/abs/2204.12484v3 【github】GitHub - ViTAE-Transformer/ViTPose: The official repo for [NeurIPS22] "ViTPose: Simple Vision Transformer Baselines for Human Pose Estimation" and [Arxiv22] "ViTPose: Vision Transformer F…

IO流操作

文章目录一、字符集常见字符集编码、解码操作二、IO流FileInputStreamFileOutputStreamFileReaderFileWriter常见问题一、字符集 常见字符集 我们的计算机底层是不可以直接存储字符的,计算机中底层只能存储二进制(0、1),同时二进制是可以转换成十进制的…

Fluent UDF编译环境配置 VS2019

Fluent UDF编译环境配置 VS2019环境配置问题记录继续记录调试过程仅用一个host仅用一个node两个都放进去换个电脑继续报错记录错误环境配置 生成PATH文件的,有的没有权限在当前文件夹,可以用这个命令,还是原来的代码,就是改一下 …

趣味三角——前言和序言

目录 1. 前言 2. 序言 2.1 抄写员Ahmes,公元前1650年 2.2 古埃及的趣味数学 1. 前言 There is perhaps nothing which so occupies the middle position of mathematics as trigonometry. (也许,没有什么东西像三角学一样占据数学的中心位置…

离散数学-图论-欧拉图、哈密顿图、二部图、平面图(14)

欧拉图、哈密顿图、二部图、平面图 1 欧拉图 无向图G是欧拉图⇔\Leftrightarrow⇔G连通,且无奇度点。无向图G是半欧拉图⇔\Leftrightarrow⇔G连通,且仅有两个奇度点。有向图G是欧拉图⇔\Leftrightarrow⇔G强连通,且所有顶点的入度出度。有向图G是半欧拉图⇔\Leftrightarrow⇔…

登录时“自动填充”和“验证码”的实现

自动填充和验证码的实现需求1. 基础登录功能1.1 持久层pojo实体类:代理接口:1.2 业务层1.3 表现层login.jsp(登陆界面):LoginServlet:selectAllServlet:brand.jsp(登陆成功&#xff…

30.Isaac教程--Costmap规划器

Costmap规划器 ISAAC教程合集地址: https://blog.csdn.net/kunhe0512/category_12163211.html 文章目录Costmap规划器组件消息入门自定义图使用自定义地图改变规划器将 Costmap 添加到视线中将通道添加到配置Isaac SDK 中的标准导航规划器指示机器人在避开障碍物的同时采用最短…

赛意SMOM和金蝶云星空单据接口对接

赛意SMOM和金蝶云星空单据接口对接数据源系统:金蝶云星空金蝶K/3Cloud在总结百万家客户管理最佳实践的基础上,提供了标准的管理模式;通过标准的业务架构:多会计准则、多币别、多地点、多组织、多税制应用框架等,有效支持企业的运营…

数据结构进阶 unordered系列的效率对比

作者:小萌新 专栏:数据结构进阶 作者简介:大二学生 希望能和大家一起进步! 本篇博客简介:对比map set和unordered系列map和set的效率 unordered系列的效率对比map/set与unordered_map/unordered_set的区别map/set与uno…

HTTP简史

今天一起来研究Http协议的一些事情,通过本文你将了解到以下内容:Http协议各版本的对比和优缺点Http2.0协议相关的SPDY协议、二进制分帧协议、多路复用、首部压缩、服务推送等基本原理HTTP3.0和QUIC协议乘风破浪前往知识的海洋吧,要开船了&…