linux gcc __attribute__
__attribute__
- 1. 函数属性
- 1.1 __attribute__((noreturn))
- 1.2 __attribute__((format))
- 1.3 __attribute__((const))
- 2. 变量属性
- 2.1. __attribute__((aligned))
- 2.2. __attribute__((packed))
- 3. 类型属性
__attribute__ 是 GCC 编译器提供的一种特殊语法,它可以用于设置函数属性(Function Attribute)、变量属性(Variable Attribute)和类型属性(Type Attribute)。
1. 函数属性
1.1 attribute((noreturn))
__attribute__((noreturn))
通常应用于那些“不会返回”的函数,即程序就直接在这个函数内退出了。例如:
- 程序异常处理
在程序遇到错误或异常时,可能需要立即终止程序并输出错误信息。这种情况下,可以使用 __attribute__((noreturn))
注解来标记一个名为 die
的函数,以确保函数执行完之后程序不会继续运行。
void die(const char* msg) __attribute__((noreturn));void die(const char* msg) {fprintf(stderr, "Error: %s\n", msg);exit(1);
}
在上面的代码中,我们定义了一个名为 die
的函数,并使用 __attribute__((noreturn))
注解表示该函数不会返回。在函数内部,我们使用 fprintf
打印错误信息,并调用 exit(1)
函数来终止程序。由于 die
函数被标记为 noreturn
,因此编译器保证在执行完 die
函数之后程序不会继续运行。
- 核心转储文件生成
在 Linux 系统中,当程序异常终止时,可以通过设置 coredump
文件来捕获程序状态和内存快照等信息,以便于进行故障排查和调试。在生成核心转储文件时,可以使用 __attribute__((noreturn))
注解来标记一个名为 abort
的函数,以确保函数执行完之后程序不会继续运行。
void abort() __attribute__((noreturn));void abort() {signal(SIGABRT, SIG_DFL);raise(SIGABRT);exit(EXIT_FAILURE);
}
在上面的代码中,我们定义了一个名为 abort
的函数,并使用 __attribute__((noreturn))
注解表示该函数不会返回。在函数内部,我们使用 signal
设置信号处理函数为默认值,并调用 raise
来生成 SIGABRT
信号,然后再调用 exit
函数来终止程序。由于 abort
函数被标记为 noreturn
,因此编译器保证在执行完 abort
函数之后程序不会继续运行。
总的来说,__attribute__((noreturn))
通常适用于那些具有明确终止程序任务的函数,例如异常处理、断言失败、致命错误等。它可以帮助开发者更好地控制程序流程和性能,并减少潜在的漏洞和错误。
1.2 attribute((format))
__attribute__((format))
用于指定函数参数的格式化字符串。它可以帮助编译器在编译时对函数调用进行检查,以确保传递给被调用函数的参数与函数定义中的格式化字符串相匹配。
使用__attribute__((format))
可以帮助编译器进行静态类型检查,以便捕获在编译时可能导致格式化字符串错误的问题。例如,如果格式化字符串中指定了一个整数参数,但实际传递给函数的是一个字符串参数,编译器将发出警告或错误消息。
以下是一个使用__attribute__((format))
的示例:
#include <stdio.h>void my_printf(const char *format, ...) __attribute__((format(printf, 1, 2)));/** 模拟标准库函数printf,它接受一个格式化字符串和可变数量的参数,并将格式化后的输出打印到标准输出。* 通过使用va_list和相关的宏来处理可变参数,函数能够将格式化字符串和参数传递给vprintf函数进行输出。* 需要注意的是,这个函数没有进行格式字符串和参数的类型检查,所以在使用时需要确保格式化字符串与参数的类型和数量相匹配,以避免潜在的运行时错误。*/
void my_printf(const char *format, ...)
{// va_list是一个类型,用于存储可变数量的参数。va_list args;// va_start宏用于初始化args,使其指向可变参数列表的起始位置。第二个参数是最后一个非可变参数,即格式化字符串format。va_start(args, format);// vprintf是一个标准C函数,用于根据格式化字符串format和可变参数列表args打印输出。它与printf函数类似,但接受一个va_list参数而不是可变数量的参数。vprintf(format, args);// va_end宏用于结束对可变参数的访问,清理相关资源。va_end(args);
}int main()
{int num = 10;my_printf("The number is: %d\n", num); // 正确的使用my_printf("The number is: %s\n", num); // 错误的使用,编译器可能会发出警告或错误消息return 0;
}
在上面的示例中,my_printf
函数使用__attribute__((format(printf, 1, 2)))
来指定它的第一个参数是格式化字符串,并且函数至少接受两个参数。这样,编译器在编译时将会检查函数调用的参数是否与格式化字符串相匹配。
应用场景
__attribute__((format))
的主要应用场景是在编写格式化输出函数(如printf
、fprintf
等)或格式化输入函数(如scanf
、fscanf
等)时,用于增加编译时的类型检查和错误检测。
以下是一些实际应用场景:
-
自定义格式化输出函数:当你需要编写自定义的格式化输出函数时,可以使用
__attribute__((format))
来确保传递给函数的参数与格式化字符串匹配。这有助于避免在运行时出现格式化字符串错误导致的问题,提高代码的健壮性和可靠性。 -
日志记录:当你编写日志记录函数时,可以使用
__attribute__((format))
来确保日志消息的格式化字符串与实际参数匹配。这样可以在编译时捕获潜在的日志格式错误,避免在运行时出现错误的日志输出。 -
静态代码分析工具:静态代码分析工具可以利用
__attribute__((format))
来检测代码中的潜在问题。通过分析函数调用和格式化字符串,这些工具可以检查是否存在格式化字符串与参数不匹配的情况,并生成警告或错误报告。
总之,__attribute__((format))
的主要应用场景是在需要进行格式化字符串的输出或输入操作时,提供编译时的类型检查和错误检测,以提高代码的安全性和可维护性。
需要注意的是,__attribute__((format))
是一个编译器特定的扩展,不是标准C或C++的一部分,因此在不同的编译器中可能会有差异。
1.3 attribute((const))
__attribute__((const))
用于标记函数为纯函数(Pure Function)。纯函数是指函数的返回值仅依赖于输入参数,而不受其他因素的影响,也不会对程序的状态产生任何可观察的副作用。
以下是关于__attribute__((const))
的一些要点:
-
纯函数属性:通过将函数标记为
__attribute__((const))
,指示编译器该函数是一个纯函数。这意味着函数的返回值仅由函数的参数决定,并且在同样的输入下,函数的返回值始终相同。 -
优化机会:将函数标记为纯函数有助于编译器进行优化。编译器可以假设对于相同的输入参数调用纯函数的两个位置,其返回值也必定相同。这种假设使得编译器可以进行常量传播(constant propagation)、公共子表达式消除(common subexpression elimination)等优化操作。
-
副作用限制:纯函数不应该对程序状态产生可观察的副作用。它们不应修改全局变量、静态变量,也不应进行I/O操作或内存分配等可能改变程序状态的操作。
-
示例用法:以下是一个示例函数,展示如何使用
__attribute__((const))
标记函数为纯函数:
int square(int x) __attribute__((const));int square(int x) {return x * x;
}
在上述示例中,square
函数被标记为纯函数。它只依赖于输入参数x
的值,并返回x
的平方。由于square
函数没有副作用,编译器可以进行进一步优化,例如在常量传播时使用已知的输入值。
总结:__attribute__((const))
函数属性用于标记函数为纯函数,以便编译器进行优化。这可以提供更好的代码优化和可读性,并确保函数没有对程序状态产生可观察的副作用。
2. 变量属性
2.1. attribute((aligned))
__attribute__((aligned(n))
是GCC和Clang编译器提供的一个属性,用于指定变量、结构体、联合体和数组的对齐方式为n字节对齐。下面是对该属性的详细解释以及几个完整示例:
__attribute__((aligned(n))
属性的解释:
__attribute__((aligned(n))
是GCC和Clang编译器的扩展语法,用于控制内存对齐方式。- 它可以应用于变量、结构体、联合体和数组等数据类型的声明。
- 通过将其放置在声明之后,可以指定所需的对齐方式,其中n表示对齐的字节数。
示例:
#include <stdio.h>struct Point
{char arr[25] __attribute__((aligned(__BIGGEST_ALIGNMENT__))); // 以当前机器支持的最大字节对齐数__BIGGEST_ALIGNMENT__来对齐char数组double x;
};struct Point2
{char arr[17] __attribute__((aligned(8))); // 以8字节对齐来对齐char数组double x;
};struct Point3
{char arr[25]; double x;
}__attribute__((aligned(__BIGGEST_ALIGNMENT__))); // 以当前机器支持的最大字节对齐数__BIGGEST_ALIGNMENT__来对齐结构体int main()
{struct Point p; // 以16字节对齐的结构体变量printf("Size of Point: %zu\n", sizeof(struct Point));printf("Size of Point2: %zu\n", sizeof(struct Point2));printf("Size of Point3: %zu\n", sizeof(struct Point3));return 0;
}
运行结果:
attribute((aligned(n)))和#pragma pack(n)的区别
__attribute__((aligned(n)))
和 #pragma pack(n)
都是用于控制内存对齐方式的机制,但它们之间存在一些区别:
-
语法:
__attribute__((aligned(n)))
是一种在 C 和 C++ 中使用的属性语法,直接应用于变量或结构体的声明。#pragma pack(n)
是一个预处理器指令,需要放置在源代码中的适当位置。
-
作用范围:
__attribute__((aligned(n)))
可以直接应用于单个变量或结构体的声明,仅影响指定的实体。#pragma pack(n)
影响其所在作用域内的所有变量或结构体的对齐方式,直到遇到另一个#pragma pack
恢复默认对齐方式。
-
兼容性:
__attribute__((aligned(n)))
是 GNU C 和一些兼容的编译器支持的语法。它在符合标准的编译器中可能无效或产生不可预测的结果。#pragma pack(n)
是一种更通用的指令,可以在多个编译器上使用,但具体行为可能会因编译器而异。
-
细粒度控制:
__attribute__((aligned(n)))
允许您对每个变量或结构体进行精确的对齐控制,可以指定不同的对齐方式。#pragma pack(n)
设置了一个全局对齐方式,会对作用范围内的所有变量或结构体生效,并且无法针对特定实体进行个别设置。
2.2. attribute((packed))
attribute((packed)) 和 #pragma pack(1) 的作用是相同的,即指定结构体或变量的紧凑对齐方式。
无论是使用 attribute((packed)) 还是 #pragma pack(1),它们都会取消默认的对齐规则,使结构体或变量的成员按照紧凑方式存储在内存中,避免因对齐而导致的额外空间浪费或与其他系统的数据格式要求不匹配。
#include <stdio.h>struct Point
{char arr[25];double x __attribute__((packed));
};int main()
{struct Point p; // 以16字节对齐的结构体变量printf("Size of Point: %zu\n", sizeof(struct Point));return 0;
}
运行结果:
3. 类型属性
通过使用 __attribute__
,可以为函数、变量、结构体、枚举等类型添加特定的属性,以便在编译过程中进行控制或优化。
以下是一些常用的 __attribute__
类型属性:
下面是对这几个 __attribute__
类型属性的简要介绍:
-
__attribute__((aligned(n)))
:这个属性用于指定变量或结构体的对齐方式。通过设置__attribute__((aligned(n)))
,您可以将变量或结构体按照 n 字节对齐。例如,attribute((aligned(4)))` 将变量或结构体按照 4 字节对齐。 -
__attribute__((packed))
:该属性用于指定结构体或变量的紧凑对齐方式。默认情况下,编译器会根据对齐规则将结构体或变量的成员对齐到特定的边界上,以提高访问效率。使用__attribute__((packed))
属性可以取消对齐规则,使结构体或变量的成员以紧凑的方式存储。 -
__attribute__((transparent_union))
:透明联合是一种特殊类型的联合,允许将联合成员与外部成员具有相同的地址。使用__attribute__((transparent_union))
属性可以在联合类型中启用这种行为。 -
__attribute__((unused))
:该属性用于告诉编译器某个函数或变量可能未被使用。通过添加__attribute__((unused))
属性,可以避免编译器产生未使用变量或函数的警告。 -
__attribute__((deprecated))
:使用该属性可以将函数或变量标记为已过时。当使用被标记为过时的函数或变量时,编译器会发出警告,提醒开发者不再推荐使用。 -
__attribute__((may_alias))
:该属性用于指示编译器该类型可能与其他类型进行别名访问,即可能会将不同类型的指针视为相同类型的别名指针。这在某些特定的编程场景中可能会有用。
相关文章:

linux gcc __attribute__
__attribute__ 1. 函数属性1.1 __attribute__((noreturn))1.2 __attribute__((format))1.3 __attribute__((const)) 2. 变量属性2.1. __attribute__((aligned))2.2. __attribute__((packed)) 3. 类型属性 __attribute__ 是 GCC 编译器提供的一种特殊语法,它可以用于…...

【SpringCloud】RabbitMQ基础
1.初识MQ 1.1.同步和异步通讯 微服务间通讯有同步和异步两种方式: 同步通讯:就像打电话,需要实时响应。 异步通讯:就像发邮件,不需要马上回复。 两种方式各有优劣,打电话可以立即得到响应,…...

css, resize 拖拉宽度
效果如下: 可直接复制预览查看属性值: 关键样式属性: resize: horizontal; overflow-x: auto; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content…...

Python识别抖音Tiktok、巨量引擎滑块验证码识别
由于最近比较忙,所以本周搞了一个相对简单的验证码,就是抖音Tiktok的滑块验证码,这也是接到客户的一个需求。这种验证码通常在电脑端登录抖音、巨量引擎的的时候出现。 首先看一下最终的效果: 验证码识别过程 1、利用爬虫采集图…...

EvilBox One靶场笔记
EvilBox: One靶场笔记 信息收集 先fscan找主机192.168.1.102 namp扫端口 开放80,22端口 然后扫目录 └─$ gobuster dir -r -u http://192.168.1.102/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x php,txt,bak,html在扫secret目录,找…...
shell脚本中的export无效
写了一段shell脚本: #!/bin/bash source Tools/simulation/gazebo-classic/setup_gazebo.bash $(pwd) $(pwd)/build/px4_sitl_default export ROS_PACKAGE_PATH$ROS_PACKAGE_PATH:$(pwd) export ROS_PACKAGE_PATH$ROS_PACKAGE_PATH:$(pwd)/Tools/simulation/gazebo…...

前沿分享-鱼形机器人
可能并不太前沿了,是21年底的新闻了,但是看见了就顺便发一下吧。 大概就是,通过在pH响应型水凝胶中编码不同的膨胀速率而构建了一种环境适应型变形微机器人,让微型机器人直接向癌细胞输送药物从而减轻药物带来副作用。 技术原理是,…...

摄像机终端IP地址白名单配置流程
海康摄像头配置白名单流程 1.登录海康摄像机前端 2.进入配置-系统-安全管理-IP地址过滤 3.IP地址过滤方式选择“允许” 4.点击添加按钮输入对应的IP地址或者IP网段 5.最后勾选启用IP地址过滤,然后保存 大华摄像头配置白名单流程 1.登录大华摄像机前端 2.进入设…...
Glibc—查看版本
方式1:直接查看ldd版本 ldd --versionldd (Buildroot) 2.30 Copyright (C) 2019 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICU…...

C++物理引擎Box2D的下载,编译,VS2013配置环境
文章目录 网站和下载地址编译工具:编译box2dhelloworld测试网站和下载地址 https://box2d.org/ 下载地址 https://hub.nuaa.cf/erincatto/box2d/tags 编译工具: 1.VS2013 2.cmake 下载地址 https://cmake.org/ 编译box2d 下载box2d源码2.4.0,解压。在box2d-2.4.0目录下…...
STL容器详解——map容器
一、map容器介绍 作为关联式容器的一种,map 容器存储的都是 pair 对象,也就是用 pair 类模板创建的键值对。其中,各个键值对的键和值可以是任意数据类型,包括 C 基本数据类型(int、double 等)、使用结构体…...

VR全景在建筑工程行业能起到哪些作用?
在建筑工程领域,数字化技术为行业的发展起到巨大的推动作用,虽然建筑施工行业主要是依赖于工人劳动力和施工设备,但是VR全景在该行业中方方面面都能应用,从设计建模到项目交付,帮助建筑师以及项目方更好的理解每个环节…...

P1257 平面上的最接近点对
题目 思路 详见加强加强版 代码 #include<bits/stdc.h> using namespace std; #define int long long const int maxn4e510; pair<int,int> a[maxn]; int n; double d1e16; pair<int,int> vl[maxn],vr[maxn]; void read() { cin>>n;for(int i1;i<…...

8月1日上课内容 第一章web基础与http协议
dns与域名 网络是基于tcp/ip协议进行通信和连接的 应用层--传输层---网络层----数据链路层-----物理层 ip地址,我们每一台主机都有一个唯一的地址标识(固定的ip地址),区分用户和计算机通信。 ip地址:32位二进制数组成的,不方便记忆 192.168.…...

Gson 添加数据默认值问题记录
问题:在用Gson add(key(string类型),value(必须是JsonElement子类))时发现,value 传了 "" 空字符串(非null),默认解析后返回null&#…...

利用Arthas+APM监控进行Java性能深度定位
大家可能都用过APM监控,包括开源的Skywalking、商用的卓豪(ZOHO)ManageEngine APM应用性能监控、以及云监控产品如听云(Server监控),这些APM监控产品大大方便了我们实时监控应用性能,并实现性能…...
【BASH】回顾与知识点梳理(十一)
【BASH】回顾与知识点梳理 十一 十一. 八至十章知识点总结及练习11.1 总结11.2 练习情境模拟题一:透过 grep 搜寻特殊字符串,并配合数据流重导向来处理大量的文件搜寻问题。情境模拟题二:使用管线命令配合正规表示法建立新指令与新变量。 该系…...

vue2-diff算法
1、diff算法是什么? diff算法是一种通过同层的树节点进行比较的高效算法。 其有两个特点: 比较只会在同层级进行,不会跨层级进行。 在diff比较的过程中,循环从两边向中间比较。 diff算法在很多场景中都有应用,在vue中&…...

SpringBoot使用redis作为缓存的实例
目录 什么是缓存? 缓存的作用? 缓存的成本? 实际项目中的应用 代码展示 什么是缓存? 缓存就是数据交换的缓冲区(称作Cache [ kʃ ] ),是存贮数据的临时地方,一般读写性能较高。 缓…...
vue3使用vue3-seamless-scroll插件
1、局部引入 import vueSeamlessScroll from "vue-seamless-scroll"; 2、注册 components: { vueSeamlessScroll, }, 3、使用 <vue3-seamless-scroll :list"list1" class"scroll" step"0.2"><div class"item"…...

Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误
HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误,它们的含义、原因和解决方法都有显著区别。以下是详细对比: 1. HTTP 406 (Not Acceptable) 含义: 客户端请求的内容类型与服务器支持的内容类型不匹…...

通过Wrangler CLI在worker中创建数据库和表
官方使用文档:Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后,会在本地和远程创建数据库: npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库: 现在,您的Cloudfla…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件
在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…...
基础测试工具使用经验
背景 vtune,perf, nsight system等基础测试工具,都是用过的,但是没有记录,都逐渐忘了。所以写这篇博客总结记录一下,只要以后发现新的用法,就记得来编辑补充一下 perf 比较基础的用法: 先改这…...
数据链路层的主要功能是什么
数据链路层(OSI模型第2层)的核心功能是在相邻网络节点(如交换机、主机)间提供可靠的数据帧传输服务,主要职责包括: 🔑 核心功能详解: 帧封装与解封装 封装: 将网络层下发…...
Python 高效图像帧提取与视频编码:实战指南
Python 高效图像帧提取与视频编码:实战指南 在音视频处理领域,图像帧提取与视频编码是基础但极具挑战性的任务。Python 结合强大的第三方库(如 OpenCV、FFmpeg、PyAV),可以高效处理视频流,实现快速帧提取、压缩编码等关键功能。本文将深入介绍如何优化这些流程,提高处理…...

yaml读取写入常见错误 (‘cannot represent an object‘, 117)
错误一:yaml.representer.RepresenterError: (‘cannot represent an object’, 117) 出现这个问题一直没找到原因,后面把yaml.safe_dump直接替换成yaml.dump,确实能保存,但出现乱码: 放弃yaml.dump,又切…...

工厂方法模式和抽象工厂方法模式的battle
1.案例直接上手 在这个案例里面,我们会实现这个普通的工厂方法,并且对比这个普通工厂方法和我们直接创建对象的差别在哪里,为什么需要一个工厂: 下面的这个是我们的这个案例里面涉及到的接口和对应的实现类: 两个发…...
AWS vs 阿里云:功能、服务与性能对比指南
在云计算领域,Amazon Web Services (AWS) 和阿里云 (Alibaba Cloud) 是全球领先的提供商,各自在功能范围、服务生态系统、性能表现和适用场景上具有独特优势。基于提供的引用[1]-[5],我将从功能、服务和性能三个方面进行结构化对比分析&#…...

RocketMQ 客户端负载均衡机制详解及最佳实践
延伸阅读:🔍「RocketMQ 中文社区」 持续更新源码解析/最佳实践,提供 RocketMQ 专家 AI 答疑服务 前言 本文介绍 RocketMQ 负载均衡机制,主要涉及负载均衡发生的时机、客户端负载均衡对消费的影响(消息堆积/消费毛刺等…...