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

news/2023/5/28 6:51:56

目录

    • 一、简介
    • 二、参数详解
      • 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.exyb.cn/news/show-4579096.html

如若内容造成侵权/违法违规/事实不符,请联系郑州代理记账网进行投诉反馈,一经查实,立即删除!

相关文章

java读取excel内容导出excel文件

1、导入maven依赖 <dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>3.17</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>p…

Excel 文件导入导出【POI】

pom 依赖 <!-- POI依赖 poi的包 3.15版本后单元格类型获取方式有调整 --><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>3.14</version></dependency><dependency><gr…

机械故障预测(Python代码实现)

目录 1 概述 2 问题 3 解答&#xff08;Python代码实现&#xff09; 3.1 任务3 3.2 任务4 1 概述 制造业是国民经济的主体&#xff0c;近十年来&#xff0c;嫦娥探月、祝融探火、北斗组网&#xff0c;一大批重大标志性创新成果引领中国制造业不断攀上新高度。作为制造业的…

熟练使用Wireshark排除网络故障的方法

1 概述 本章会讨论如何娴熟地将Wireshark作为网络排障工具来使用&#xff0c;先讲如何配置用户界面&#xff0c;再谈如何配置全局和协议参数&#xff0c;接下来将讨论Wireshark文件夹、配置文件、文件夹和插件[3] 。 本章还会讲解Wireshark的配色规则及配置方法&#xff0c;…

poi导入excel数据到数据库

导入poi依赖 <properties><poi.version>3.17</poi.version></properties> <!-- POI --><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>${poi.version}</version…

java excel 插件开发工具_程序员常用的15 种开发者工具推荐

程序员常用的15 种开发者工具推荐&#xff1a;Java 线上诊断工具 Arthas、IDE 插件 Cloud Toolkit、混沌实验注入工具 ChaosBlade、Java 代码规约扫描插件、应用实时监控工具 ARMS、静态开源站点搭建工具 Docsite、Android 平台上的秒级编译方案 Freeline等开发工具。程序员常用…

java按需导出Excel并自动合同单元格

java导出excel并单元格自动合并 最近公司有一个需求,就是按到模版导出数据报表,并内容相同的单元格实现自动合并.具体业务设计图如下所示 需求分析 由于头部是固定不变的,先使用excel创建数据模版单元格合并,前三列需要根据内容相同自动合并单元格根据状态来判断,状态异常的红…

基于SpringBoot+Mysql的模拟风电场监控系统

目录 一、项目概述 1 二、系统设计 2 2.1 设计目标 2 2.2 系统设计原则 2 三、数据设计 2 四、菜单设计 3 4.1.主页 3 4.2.全场监控 3 4.3.数据统计 3 4.4.报表管理 4 4.5.报警管理 4 五、 数据库设计 4 5.1 物理视图 4 5.2 E-R 图 5 六、系统功能 7 6.1 完整实时数据展现 7 6.…

Swin Transformer代码实战篇

&#x1f34a;作者简介&#xff1a;秃头小苏&#xff0c;致力于用最通俗的语言描述问题 &#x1f34a;往期回顾&#xff1a;CV攻城狮入门VIT(vision transformer)之旅——近年超火的Transformer你再不了解就晚了&#xff01; CV攻城狮入门VIT(vision transformer)之旅——VIT原…

信用卡千万不要这样用

信用卡 成年人之必备 饭票、影票活动花样多多 还能解决没钱时的不时之需 真可谓是&#xff0c;一卡走遍天下都不怕 即便是现在信用卡广泛被人们使用&#xff0c;但很多人其实并不真正了解信用卡&#xff0c;甚至因为使用不当而造成额外损失。对于很多用卡小白切记不要范以…

【JavaEE】单例模式(饿汉懒汉)

目录 前言&#xff1a; 单线程下的单例模式 饿汉模式 懒汉模式 多线程下的单例模式 懒汉模式的修改 1.加锁 2.有条件的加锁 3.解决内存可见性和指令重排序 前言&#xff1a; 本片文章介绍设计模式中的一个模式——单例模式。 单例模式就是只允许创建出一个实例的类。…

正则中\cx是什么意思

\cx 匹配control 控制字符&#xff0c;就是说 匹配由x指明的控制字符 这里的X是一个控制字符。匹配一个字符串的控制字符。 比如&#xff1a; \cI 匹配 control I&#xff0c;等价于 \t&#xff0c; \cJ匹配 control J&#xff0c;等价于 \n, \cM匹配 control M&#xff…

[C++]C++/CX 编程简述

C/CX 是windows运行时的C语法。它是属于Native C&#xff0c;不使用CLR也没有垃圾回收机制&#xff0c;与.Net平台下扩展的C/CLR有本质的区别&#xff0c;虽然两者语法比较类似&#xff0c;但是这两者是完全不同的。C/CX是基于Windows运行时而诞生的&#xff0c;它运行在Window…

离散数学-集合论-函数(10)

函数 1 函数的概念 1.1 函数的定义 设&#x1d453;是非空集A到B的关系, 如果对每个&#x1d465;∈A, 都存在唯一的&#x1d466;∈B, 使得<&#x1d465;, &#x1d466;>∈&#x1d453;, 则称关系&#x1d453;为A到B的函数(Function), 也可称为映射(Mapping)或变…

allegro使用汇总 [转贴]

1.如何在allegro中取消花焊盘(十字焊盘) set up->design parameter ->shape->edit global dynamic shape parameters->Thermal relief connects ->Thru pins ,Smd pins -> full contact 2.allegro 中如何设置等长 setup -> constraints->electrical-&g…

AUTOCAD二次开发工具

ARX(AutoCAD Runtime eXtension实时运行扩展)作为继AutoLISP、ADS后的第三代开发工具&#xff0c;采用全新的面向对象编程技术。1985年6月推出的AutoCAD2.17版本使用AutoLISP作为AUTOCAD内嵌语言&#xff0c;与AUTOCAD绑定一起&#xff0c;向用户提供了用AutoLISP设计应用程序的…

03-07 创建和编辑AutoCAD实体(七) 向图形中添加文字(3)使用多行文字

3、Use MultilineText (MText)使用多行文字&#xff08;MText命令&#xff09; For long, complex entries, createmultiline text (MText). Multiline text fits a specified width but can extendvertically to an indefinite length. You can format individual words orch…

rtthread pwm

1、配置PWM设备驱动相关宏定义 1.1 配置PWM和TIM设备驱动 在RT-Thread Settings 配置界面中&#xff0c;在设备驱动程序目录下勾选 HWTIMER 和 PWM设备驱动程序&#xff0c;如下图所示&#xff1a; 配置完后在 rtconfig.h 中可以查看刚刚配置的 RT_USING_HWTIMER 和 RT_U…

抠图再也不用ps啦

大家在处理图片的时候经常会为了抠图头大吧.... 尤其是没有PS基础的小编们,特别费劲的用ps软件慢慢的抠图&#xff0c;效果还不满意真是心累呀~ 制作微信公众号文章中想要设置透明的图片放到背景图里&#xff0c;抠图是必须要做的一件事&#xff0c;这边给大家介绍下如何快速…

怎么批量抠复杂的图_PhotoShop怎么抠图?ps最简单的抠图方法是什么?

步骤1&#xff1a;正确选择图片为了获得最佳效果&#xff0c;您的图像应 在要剪切的对象和背景之间具有 最大的分辨率和对比度。这对于快速&#xff0c;干净地排除对象至关重要。步骤2&#xff1a;选择主题要应用新的“选择主题”功能&#xff0c;在Photoshop CC 2018&#xff…