当前位置: 首页 > news >正文

GNU C编译器扩展关键字:__attribute__

目录

一、section

二、aligned

三、packed

四、format

五、weak

六、alias

七、noinline和always_inline


GNU C增加了一个__attribute__关键字用来声明一个函数、变量或类型的特殊属性,可以知道编译器在编译过程中进行特定方面的优化或代码检查。

目前,__attribute__属性支持十几种属性声明:

section、aligned、packed、format、weak.......

一、section

section属性的作用是在程序编译时,将一个函数或变量放到指定的段,即section中。

一个可执行文件主要由代码段、数据段、BSS段构成。除了这三个段之外,可执行文件还包含其他一些段,如只读数据段,符号表等。在Linux系统中,可以使用readelf -S命令查看一个可执行文件的各个端信息,包括大小、起始地址等。

一般默认规则为

section组成
代码段(.text)函数定义、程序语句
数据段(.data)初始化的全局变量、初始化的静态局部变量
BSS段(.bss)未初始化的全局变量、未初始化的静态局部变量

 使用举例:

int val0 = 8;
int val1 __attribute__((section(".data")));
int main(void)
{return 0;
}

 此时我们用readelf查看,可以发现val1放在了数据段中。

二、aligned

aligned和packed是用来显式指定一个变量的存储对齐方式。aligned一般用来增大变量的地址对齐。

C语言中各种基本数据类型要按照自然边界对齐:一个char型的变量按照1字节对齐,一个short行的整型变量按照sizeof(short int)=2字节对齐,一个int型的整型变量要按sizeof(int)=4字节对齐。

C语言中不仅基本数据类型要按照自然边界对齐,复合数据类型也要按照各自的对其原则对齐。

结构体对齐原则如下:

  • 结构体内各成员按照各自数据类型的对齐模数对齐。
  • 结构体整体对齐方式:按照最大成员的size或其size的整数倍对齐。

联合体对齐原则如下:

  • 联合体的整体大小:最大成员对齐模数或对齐模数的整数倍。
  • 联合体的对齐原则:按照最大成员的对齐模数对齐。

如果你想定义一个变量,在内存中以8字节地址对齐,就可以如下:

int a __attribute__((aligned(8)));

 更甚,我们可以显式指定结构体内某个成员的地址对齐,也可以显示指定整个结构体的对齐方式。如:

struct data {char a;short b __attribute__((aligned(4)));int c;
}struct data {char a;short b;int c;
}__attribute__((aligned(16)));

 需要注意的是,编译器对每个基本数据类型都有默认的最大边界对齐字节数,如果超过了,编译器只能按照它规定的最大对齐字节数给变量分配地址。

总结:通过aligned属性声明,可以显示的指定变量的对齐方式,简化CPU和内存RAM之间的接口和硬件设计,但是也会因为边界对齐造成一定的内存空洞,浪费内存资源。

三、packed

aligned和packed是用来显式指定一个变量的存储对齐方式。packed一般用来减少变量的地址对齐。指定变量或类型使用最可能小的地址对齐方式。

如:

struct data {char a;short b __attribute__((packed));int c __attribute__((packed));
}struct data {char a;short b;int c;
}__attribute__((packed));

 这两种方式,结构体大小都为7。对整个结构体添加packed属性和分别对每个成员添加packed属性是一样的。

在内核源码中,我们经常看到aligned和packed一起使用,这样既避免了结构体内各成员因地址对齐产生内存空洞,又指定了整个结构体的对齐方式。

struct data {char a;short b;int c;
}__attribute__((packed,aligned(8)));

 这个结构体大小为8。

四、format

format属性可以指定变参函数的参数格式检查。

例如,我们实现一个自己的打印函数,为了确保传入参数的格式正确性,可以添加该属性。如:

#include <stdio.h>
#include <stdarg.h>
/*va_list:定义在编译器头文件stdarg.h中。va_start(fmt, args):根据参数args的地址,获取args后面参数的地址,并保存在fmt指针变量中va_end(args):释放args指针,将其赋值为NULL
*/void __attribute__((format(printf,1,2))) my_printf(char a, ...)
{va_list args;va_start(args, a);vprintf(a, args);va_end(args);
}int main(void)
{int num = 0;my_printf("hello world!\n", num);return 0;
}

五、weak

weak属性可以将一个强符号转换为弱符号。

使用方法如下:

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

强符号:函数名,初始化的全局变量名。

弱符号:未初始化的全局变量名。

 使用举例:

int a __attribute__((weak)) = 1;void f(void)
{printf("f:a = %d\n", a);
}int a = 4;int main(void)
{printf("main:a = %d\n", a);f();return 0;
}

程序运行结果如下:

main:a = 4
f:a = 4

六、alias

alias属性主要用来给函数定义一个别名。

void _f(void)
{printf("_f\n");
}void f() __attribute__((alias("_f")));int main(void)
{f();return 0;
}

程序运行结果如下:

_f

通过alias属性声明,我们给_f()函数定义了一个别名f(),以后如果想要调用_f()函数,则直接通过f()调用即可。

在Linux内核中,我们会发现alias有时会和weak属性一起使用。特别是当有些函数随着内核版本升级,函数接口发生了变化,我们可以通过alias属性对这个旧的接口名字进行封装,重新起一个接口名字。

//f.c
void _f(void)
{printf("_f()\n");
}void f() __attribute__((weak, alias("_f")));//main.c
void __attribute__((weak)) f(void);
void f(void)
{printf("f()\n");
}
int main(void)
{f();return 0;
}

如果我们在main.c中重新定义了f()函数,那么当main()函数调用f()函数时,会直接调用main.c中新定义的函数;当f()函数没有被定义时,则调用_f()函数。

七、noinline和always_inline

这两个属性的用途是告诉编译器,在编译时,对我们指定的函数内联展开或不展开。

使用方法为:

static inline __attribute__((noinline)) int func();
static inline __attribute__((always_inline)) int func();

使用inline声明的函数被称为内联函数,内联函数一般会有一个static或extern修饰。使用inline声明一个内联函数,和使用关键字register声明一个寄存器变量一样,只是建议编译器在编译时内联展开。编译器会根据实际情况(函数体大小、)来做决定。使用register修饰一个变量时,只是建议编译器在为变量分配存储空间时,将这个变量放到寄存器里,使程序的运行效率更高。编译器会根据寄存器资源是否紧张,这个变量的类型及是否频繁使用来做权衡。

但是,我们使用noinline和always_inline对一个内联函数做显式属性声明时,编译器的编译行为就变得确定了:使用noinline声明,就是告诉编译器不要展开;使用always_inline属性声明,就是告诉编译器要内联展开。

相关文章:

GNU C编译器扩展关键字:__attribute__

目录 一、section 二、aligned 三、packed 四、format 五、weak 六、alias 七、noinline和always_inline GNU C增加了一个__attribute__关键字用来声明一个函数、变量或类型的特殊属性&#xff0c;可以知道编译器在编译过程中进行特定方面的优化或代码检查。 目前&…...

C++基础 | 从C到C++快速过渡

一、开发环境 c使用的编译器是g。 vim或者vscodeclionVS 二、C版本的Hello World /*** brief c版本helloworld示例* author Mculover666* date 2023/2/26*/#include <iostream> using namespace std;int main() {int a 1;double b 3.14;char c[] "str…...

【C++】仿函数 -- priority_queue

文章目录一、priority_queue 的介绍和使用1、priority_queue 的介绍2、priority_queue 的使用3、priority_queue 相关 OJ 题二、仿函数1、什么是仿函数2、仿函数的作用三、priority_queue 的模拟实现一、priority_queue 的介绍和使用 1、priority_queue 的介绍 priority_queu…...

盘一盘C++的类型描述符(一)

前言 C的类型描述方式是从C语言继承来的&#xff0c;并且进行了扩充&#xff08;例如引用、非静态成员函数、模板实参等&#xff09;。但由于C语言中的类型描述方式就略微有点「反人类」&#xff0c;再经C扩展后就有点「反碳基生物」了~ 是的&#xff0c;当我第一次看到这种描…...

Peppol的发展史和基本框架

Peppol&#xff08;Pan-European Public Procurement Online&#xff09;是欧洲区域内的一个跨境公共采购电子商务平台试点项目&#xff0c;由欧盟委员会和Peppol联盟成员国共同资助建立&#xff0c;旨在通过制定标准化框架&#xff0c;推动欧盟成员国在公共采购相关的电子目录…...

Linux-GCC介绍+入门级Makefile使用

前言&#xff08;1&#xff09;我们都知道&#xff0c;在Linux中编译.c文件需要使用gcc -o .c文件的指令来将C文件变成可执行文件。但是我们有没有发现&#xff0c;如果我们需要编译大一点的工程&#xff0c;后面需要加上的.c文件是不是太多了&#xff1f;感觉非常的麻烦。&…...

iOS(一):Swift纯代码模式iOS开发入门教程

Swift纯代码模式iOS开发入门教程项目初始化&#xff08;修改为纯代码项目&#xff09;安装第三方库&#xff08;以SnapKit库为例&#xff09;桥接OC库&#xff08;QMUIKit&#xff09;封装视图并进行导航跳转示例&#xff1a;使用 TangramKit 第三方UI布局库应用国际化添加 R.s…...

IDEA+Python+Selenium+360浏览器自动化测试

环境配置前提&#xff0c;见文章https://mp.csdn.net/mp_blog/creation/editor/new?spm1001.2101.3001.4503下载360浏览器&#xff0c;并下载对应版本的chromedriver.exe&#xff0c;下载地址http://chromedriver.storage.googleapis.com/index.html下载好360浏览器&#xff0…...

运输层概述及web请求

运输层 运输层概述 运输层向高层用户屏蔽了下面网络核心的细节&#xff08;如网络拓扑、所采用的路由选择协议等&#xff09;它使应用进程看见的就好像是在两个运输层实体之间有一条端到端的逻辑通信信道&#xff1b; 根据需求不同&#xff0c;运输层提供两种运输协议 面向连…...

python与pycharm从零安装

python&#xff08;解释器&#xff09;下载地址&#xff1a;Welcome to Python.orgpycharm&#xff08;编译器&#xff09;下载地址&#xff1a;PyCharm: the Python IDE for Professional Developers by JetBrains一、python的下载与安装到官网后根据步骤下载安装包后&#xf…...

叠氮试剂943858-70-6,Azidobutyric acid NHS ester,叠氮-C3-活性酯

1、试剂基团反应特点&#xff08;Reagent group reaction characteristics&#xff09;&#xff1a;Azidobutyric acid NHS ester具有叠氮化物和NHS酯端基。西安凯新生物科技有限公司供应的叠氮化物可以与炔烃、DBCO和BCN进行铜催化的点击化学反应。NHS酯可以与胺基反应&#x…...

pycharm激活虚拟环境时报错:无法加载文件activate.ps1,因为在此系统上禁止运行脚本,Windows10系统

问题&#xff1a; ii_env\Scripts\activate : 无法加载文件 F:\gitlab\AutoFrame\ii_env\Scripts\Activate.ps1&#xff0c;因为在此系统上禁止运行脚本。 有关详细信息&#xff0c;请参阅 https:/go.microsoft.com/fwlink/?LinkID135170 中的 about_Execution_Policies。 所在…...

刷题小抄4-数组

在Python中数组的功能由列表来实现,本文主要介绍一些力扣上关于数组的题目解法 寻找数组中重复的数字 题目链接 题目大意: 给出一个数组,数组长度为n,数组里的数字在[0,n-1]范围以内,数字可以重复,寻找出数组中任意一个重复的数字,返回结果 解法一 该题最基础的思路是使用字…...

Hbase安装

目录 上传压缩包 解压 改名 修改 Hbase 配置文件 修改base-env.sh 修改hbase-site.xml 配置环境变量 修改zookeeper配置文件 复制配置文件 修改zoo.cfg配置文件 修改myid 配置环境变量 刷新配置文件 启动Hbase 进入Hbase 查看版本号 查看命名空间 查看命名空…...

面向对象设计模式:结构型模式之代理模式

一、引入 访问 FB&#xff1a;代理服务器 二、代理模式 aka Surrogate 2.1 Intent 意图 Provide a surrogate (代理) or placeholder for another object to control access to it. 为另一个对象提供一个代理或占位符&#xff0c;以控制对它的访问。代理模式给某一个对象提…...

CCF大数据专家委员会十周年纪念庆典纪实:拥抱数字时代,展望科技未来

山河远阔&#xff0c;奋进十年&#xff0c;作为国内大数据领域最权威的学术组织&#xff0c;CCF大数据专家委员会&#xff08;以下简称“大专委”&#xff09;不忘初心&#xff0c;凝心聚力&#xff0c;见证并推动了过去10年来大数据技术生态在中国的建立、发展和成熟。 2023年…...

Qt学习3-Qt Creator四则运算计算器(哔站视频学习记录)

计算器中的“”按钮这部分的代码解释 目录 制作计算器中的“”按钮这部分的代码解释 一、代码部分 二、解释 三、思路 四、死循环&#xff01; 一、代码部分 void Widget::on_equalButton_clicked() {QStack<int> s_num,s_opt; //声明两个int类型变量char opt[128…...

学习 Python 之 Pygame 开发魂斗罗(九)

学习 Python 之 Pygame 开发魂斗罗&#xff08;九&#xff09;继续编写魂斗罗1. 在子弹类中修改敌人发射子弹的位置2. 创建显示敌人子弹的函数3. 解决敌人不会向下掉落的问题4. 给敌人碰撞体组增加碰撞体5. 解决敌人叠加在一起的问题继续编写魂斗罗 在上次的博客学习 Python 之…...

最简单的SpringBoot+MyBatis多数据源实现

最简单的SpringBootMyBatis多数据源实现1.数据库准备2.环境准备3.代码部分3.1多数据源配置2.测试随着应用用户数量的增加&#xff0c;相应的并发请求的数量也会跟着不断增加&#xff0c;慢慢地&#xff0c;单个数据库已经没有办法满足频繁的数据库操作请求了&#xff0c;在某些…...

Spring Boot 3.0系列【8】核心特性篇之SpringApplication

有道无术,术尚可求,有术无道,止于术。 本系列Spring Boot版本3.0.3 源码地址:https://gitee.com/pearl-organization/study-spring-boot3 文章目录 前言1. 启动应用2. 自定义 Banner3. 应用参数传递参数获取参数4. ApplicationRunner、CommandLineRunner5. 事件发布和监听…...

练习(含atoi的模拟实现,自定义类型等练习)

一、结构体大小的计算及位段 &#xff08;结构体大小计算及位段 详解请看&#xff1a;自定义类型&#xff1a;结构体进阶-CSDN博客&#xff09; 1.在32位系统环境&#xff0c;编译选项为4字节对齐&#xff0c;那么sizeof(A)和sizeof(B)是多少&#xff1f; #pragma pack(4)st…...

Leetcode 3577. Count the Number of Computer Unlocking Permutations

Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接&#xff1a;3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯&#xff0c;要想要能够将所有的电脑解锁&#x…...

linux 错误码总结

1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

css的定位(position)详解:相对定位 绝对定位 固定定位

在 CSS 中&#xff0c;元素的定位通过 position 属性控制&#xff0c;共有 5 种定位模式&#xff1a;static&#xff08;静态定位&#xff09;、relative&#xff08;相对定位&#xff09;、absolute&#xff08;绝对定位&#xff09;、fixed&#xff08;固定定位&#xff09;和…...

Spring AI 入门:Java 开发者的生成式 AI 实践之路

一、Spring AI 简介 在人工智能技术快速迭代的今天&#xff0c;Spring AI 作为 Spring 生态系统的新生力量&#xff0c;正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务&#xff08;如 OpenAI、Anthropic&#xff09;的无缝对接&…...

如何理解 IP 数据报中的 TTL?

目录 前言理解 前言 面试灵魂一问&#xff1a;说说对 IP 数据报中 TTL 的理解&#xff1f;我们都知道&#xff0c;IP 数据报由首部和数据两部分组成&#xff0c;首部又分为两部分&#xff1a;固定部分和可变部分&#xff0c;共占 20 字节&#xff0c;而即将讨论的 TTL 就位于首…...

2023赣州旅游投资集团

单选题 1.“不登高山&#xff0c;不知天之高也&#xff1b;不临深溪&#xff0c;不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...

九天毕昇深度学习平台 | 如何安装库?

pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子&#xff1a; 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA

浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求&#xff0c;本次涉及的主要是收费汇聚交换机的配置&#xff0c;浪潮网络设备在高速项目很少&#xff0c;通…...

渗透实战PortSwigger靶场:lab13存储型DOM XSS详解

进来是需要留言的&#xff0c;先用做简单的 html 标签测试 发现面的</h1>不见了 数据包中找到了一个loadCommentsWithVulnerableEscapeHtml.js 他是把用户输入的<>进行 html 编码&#xff0c;输入的<>当成字符串处理回显到页面中&#xff0c;看来只是把用户输…...