GCC __ATTRIBUTE__机制

__attribute__关键字在C语言中用于设置函数、变量和类型的属性,如函数参数传递、内存对齐等。文章举例说明了如何使用__attribute__((aligned))进行内存对齐,使用__attribute__((constructor))和__attribute__((destructor))定义构造和析构函数,以及__attribute__((regparm))在x86平台上指定函数参数使用寄存器的方式。

在glibc源代码中你可能会看到大量的__attribute__关键字,譬如常用的stdio.h中开头处就能见到它的身影了

#ifndef _STDIO_H
# if defined __need_FILE || defined __need___FILE || defined _ISOMAC
#  include <libio/stdio.h>
# else
#  include <libio/stdio.h>

/* Now define the internal interfaces.  */
__BEGIN_DECLS

extern int __fcloseall (void);
extern int __snprintf (char *__restrict __s, size_t __maxlen,
		       const char *__restrict __format, ...)
     __attribute__ ((__format__ (__printf__, 3, 4)));
extern int __vsnprintf (char *__restrict __s, size_t __maxlen,
			const char *__restrict __format, _G_va_list __arg)
     __attribute__ ((__format__ (__printf__, 3, 0)));
extern int __vfscanf (FILE *__restrict __s,
		      const char *__restrict __format,
		      _G_va_list __arg)
     __attribute__ ((__format__ (__scanf__, 2, 0)));
libc_hidden_proto (__vfscanf)
extern int __vscanf (const char *__restrict __format,
		     _G_va_list __arg)
     __attribute__ ((__format__ (__scanf__, 1, 0)));
extern _IO_ssize_t __getline (char **__lineptr, size_t *__n,
			      FILE *__stream);
extern int __vsscanf (const char *__restrict __s,
		      const char *__restrict __format,
		      _G_va_list __arg)
     __attribute__ ((__format__ (__scanf__, 2, 0)));

作用

用于设置函数属性(Function Attribute )、变量属性(Variable Attribute )和类型属性(Type Attribute )

书写格式

__attribute__ ((attribute-list)) //括弧里面是相应的__attribute__ 参数

常用格式

用于结构体中有大致六个参数值可以被设定,即:aligned, packed, transparent_union, unused, deprecated 和 may_alias

一般会采用__aligned__格式代替aligned是为了避免头文件中的重名冲突

aligned实例

#include<stdio.h>
#include <asm/types.h>

struct H{
	short b[3];
};
struct S{
	short b[3];
}__attribute((aligned(16))); //设定结构体属性按16字节单位对齐 

struct str_struct{
    __u64   e; 
    __u8    a;
    __u8    b;
    __u8    c;
    __u16   d;
} __attribute__ ((packed));//按照实际大小进行对齐,取消编译优化


int main(){
    struct S s;
    struct H h;
    printf("%d\n",sizeof(s)); // 16
    printf("%d\n",sizeof(h)); // 6
    printf("%d\n",sizeof(str)); // 13
    return 0;
}

aligned 属性使被设置的对象占用更多的空间,相反packed 可以减小对象占用的空间

作用于构造函数

#include <stdio.h>
#include <stdlib.h>

__attribute__((constructor)) void before()//将该函数声明为构造函数,会在main函数前执行
{
    printf("Hello");
}

__attribute__((destructor)) void after()//将该函数声明为结束函数,main函数结束后执行
{
    printf(" World!\n");
}

int main(int args,char ** argv)
{
    return EXIT_SUCCESS;
}
//输出:Hello World\n

在需要使用执行前不同处理函数级别时,可指定函数的优先级如下:__attribute__((constructor(PRIORITY)))

#include <stdio.h>
#include <stdlib.h>

__attribute__((constructor(102))) void before()
{
    printf("Hello");
}
__attribute__((constructor(101))) void in_before() //指定优先级高于brfore()
{
    printf("Look me! ");
}

__attribute__((destructor)) void after()
{
    printf(" World!\n");
}

int main(int args,char ** argv)
{
    return EXIT_SUCCESS;
}
//输出:Look me! Hello World\n

需要注意的是PRIORITY的值0~100作为系统内部使用

regparm实例

在 x86 上,regparm 属性会传递一个数值给编译器,这个数值会告诉编译器要用多少个寄存器来传递函数参数(EAX, EDX 或 ECX,最多 3 个寄存器)

//gcc -o demo3 -w -g -m32 demo3.c
#include<stdio.h>

size_t info(int a, int b){
    return a+b;
}
__attribute__((regparm(3))) size_t in_info(int a, int b){//声明该函数参数由3个寄存器来传输,0则由栈传输
    return a+b;
}
int main(){
    in_info(5,5);  //只限于intel i386架构!!
                ¦  /*
                    *→ 0x56555532 <main+13>        mov    edx, 0x5
                    ¦  0x56555537 <main+18>        mov    eax, 0x5
                    ¦  0x5655553c <main+23>        call   0x56555504 <in_info>
                    * */
    return 0;
}

资料参考:https://www.cnblogs.com/the-tops/p/5885464.html

### 关于 `___attribute__` 的用法和含义 在 C 和 C++ 中,`___attribute__` 是一种 GNU 扩展语法,用于向编译器提供额外的信息或修改某些行为。它通常由 GCC 编译器支持,并允许开发者通过指定属性来优化代码性能、改进调试体验以及增强程序的安全性。 #### 属性的基本结构 `___attribute__` 的基本形式如下: ```c ___attribute__((attribute_list)) ``` 其中 `attribute_list` 表示一系列逗号分隔的属性名称及其参数。这些属性会影响声明的对象(如变量、函数或类型)的行为。 --- #### 常见用途及例子 1. **函数属性** 函数可以通过 `___attribute__` 来定义特定的行为。例如,标记某个函数不会返回 (`noreturn`) 或者总是内联展开 (`always_inline`)。 ```c void my_exit_function(void) ___attribute__((noreturn)); ``` 上述代码表示该函数一旦执行就不会再返回到调用处[^5]。 2. **变量属性** 变量也可以应用属性以改变其存储方式或其他特性。比如使用 `aligned` 属性可以让数据按照指定字节边界对齐: ```c int data ___attribute__((aligned(16))); ``` 这里指定了 `data` 应当按 16 字节对齐[^6]。 3. **类型属性** 对自定义的数据类型设置特殊处理规则也是可能的。例如创建一个新的整数类型并强制对其成员进行严格别名检查(`may_alias`): ```c typedef int new_int_type ___attribute__((may_alias)); ``` 此操作使得即使违反了严格的类型匹配原则也不会引发未定义行为[^7]。 4. **段落属性 (Section Attribute)** 将全局对象放置在一个特别命名的部分中对于嵌入式开发尤其有用: ```c int special_var ___attribute__((section(".my_section"))); ``` 把变量放入名为 `.my_section` 的部分有助于管理内存布局或者与其他硬件资源交互[^8]。 --- #### 注意事项 尽管 `___attribute__` 提供了许多强大的功能,但在实际项目中应当谨慎使用它们。因为这属于非标准扩展,在跨平台移植时可能会遇到兼容性问题。如果目标环境不支持相同的编译选项,则需要考虑替代方案或将此类依赖抽象出来以便维护。 --- ### 结合其他引用的理解补充说明 虽然上述解释主要围绕 `___attribute__` 开展讨论,但是为了更全面理解整个上下文中提到的技术概念,这里还简单提及几个相关内容作为对比学习材料: - 访问控制机制中的 `protected`: 它限定了类内部成员访问权限范围仅限本体加子代继承关系之内[^2]; - Python 的胶囊导入工具(PyCapsule_Import()): 主要服务于动态加载共享库接口场景下验证一致性需求[^3]; - TensorFlow 队列操作实例展示了张量队列取出元素过程[^4]. 以上均体现了不同编程语言各自特色化设计思路和技术实现细节差异之处. ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值