gnu C语言__attribute__作用

关于attribute

在看linux源码的时候我们可能会经常碰见相关的东西,比如在dl_open的函数里边:

void* internal_function 
  _dl_open (const char *file, int mode, const void *caller)
  {
     struct dl_open_args args;

       __rtld_lock_lock_recursive (GL(dl_load_lock));

     args.file = file;
     args.mode = mode;
     args.caller = caller;
     args.map = NULL;

     dl_open_worker(&args);
        __rtld_lock_unlock_recursive (GL(dl_load_lock));

  }

这里的internal_function就是一个attribute的应用,其具体格式是:

#define internal_function __attribute__ ((regparm (3), stdcall))

attribute顾名思义,是说明函数(甚至是变量和结构体)的一些属性,这样给编译器提供更多的信息,我们在这里说明一些常用的attribute的用法。

注意

gnu cc需要用 -Wall来激活这个选项

用法

1 格式判断 format

说明:即按照格式字符串来判断参数的合法性,如果不合法则编译器给出warning
具体格式:attribute(format(type, string_index, first_to_check))
解释: type填scanf或者printf,表示用scanf或者printf的方式进行检测,string_index表示格式字符串是函数的第几个参数,最后first_to_check表示需要检查的参数位于函数的那个位置
示例:

void myPrint(const char* format_string, ...)
__attribute__(format(printf, 1, 2));//format_string是格式化字符串,后面的...是需要检测的参数
//格式化字符串位于第一个,而需要检测的参数位于函数的第二个,所以是format(printf, 1, 2)
//即string_index = 1, first_to_check = 2

2 函数不返回给调用者 noreturn

说明:表明该函数不需要返回给调用者,避免一些不必要的优化
具体格式:attribute((noreturn))
示例:

void myExit() __attribute__((noreturn));

3 const attribute

说明:这个属性主要用于没有静态状态和副作用的函数,其返回值主要依赖于输入值,且只能用于带有数值类型的函数,不能用于带有指针类型参数的函数
具体格式:attribute((const))
示例:

void intSqrt(int x)__attribute__((const))
//由于sqrt操作只依赖于x的输入,这样再调用相同的数值的时候会得到同样的输出,const就是针对这一类函数
//当重复调用同一个数值的时候,编译器会优化,使其只进行一次运算,而后来的调用都返回第一次的结果即可

4 no_instrument_function

说明:这个属性解释起来较为复杂,因为涉及到gcc的一个编译选项,-finstumat-function.添加了该参数,在编译的时候将会生成instrumentation调用,即在一个函数入口之后,和出口之前调用两个函数,分别是:

void __cyg_profile_func_enter(void *this_fn, void *call_site);
void __cyg_profile_func_exit(void *this_fn, void *call_site);
//profile函数

而不需要生成instrumentation调用的函数则使用该属性标明,典型的用法比如profile函数本身,高优先级的中断例程以及任何不能保证profiling正常调用的函数。
具体格式:attribute((no_instrument_function))
示例:

//test.c
#include <stdio.h>
void __cyg_profile_func_enter(void *, void *)
    __attribute__((no_instrument_function));
void __cyg_profile_func_exit(void *, void *)
    __attribute__((no_instrument_function));
void __cyg_profile_func_exit(void *this_fn, void *call_site)
{
    printf("this_func: %p call_addr: %p\n", this_fn, call_site);
}

void __cyg_profile_func_enter(void *this_fn, void *call_site)
{
    printf("this_func: %p call_addr: %p\n", this_fn, call_site);
}
int main()
{
    printf("hey, everybody!\n");
    return 0;
}

编译命令:

gcc -o test test.c -finstrument-functions

输出结果:(我是64位系统)

this_func: 0x400645 call_addr: 0x7feebbbd8f45
hey, everybody!
this_func: 0x400645 call_addr: 0x7feebbbd8f45

5 constructor/destructor属性

说明:主要用于对函数的初始化等,如果声明了constructor属性,则会在main函数之前执行,如果声明了destructor属性则会在main函数执行之后,或者exit被调用后自动执行。
具体格式:
attribute((constructor))
attribute((destructor))
示例:

//test.c
#include <stdio.h>
void constructor_func()
    __attribute__((constructor));
void destructor_func()
    __attribute__((destructor));
void constructor_func()
{
    printf("I am a constructor :)\n");
}
void destructor_func()
{
    printf("I am a destructor :)\n");
}
int main()
{
    printf("I am main, I did nothing! :(\n");
    return 0;
}

编译选项:

gcc -o test test.c

运行结果:

I am a constructor :)
I am main, I did nothing! :(
I am a destructor :)

6 变量属性

说明:之前我们提到的所有设置,都是对函数进行设置,这里,除了对函数进行设置,也可以对变量和结构体进行属性设置
常见变量属性:

  • aligned,指明对齐格式:int x[3] __attrubute__((aligned(16)))即16字节对齐。(使对象占用更多空间)
  • packed,使用最小对齐方式。int x[3] __attribute__((packed))(减少对象所占用空间)

在此我就不列出了,见更多变量属性

7 类型属性

说明:就像变量属性是对变量的属性声明,类型属性就是对类型的属性声明。主要是对struct和union进行属性声明,这里不再赘述,和第6点比较类似,更多类型属性见此

tips

  • attribute中的属性可以前后加双下划线以避免宏重复。
  • 可以用一个attribute指明多个属性,如__attrubute__((noreturn, format(printf, 1, 2))),当然也可以写多个attribute,如__attribute__((noreturn)) __attribute__((format(printf, 1, 2)))
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
__attribute__是一个编译属性,用于向编译器描述特殊的标识、错误检查或高级优化。它是GNU C的一个特性,可以用于设置函数属性、变量属性和类型属性等。在给函数、变量或类型添加属性时,可以使用__attribute__来指定属性列表。例如,可以使用__attribute__((constructor))来在main函数执行之前执行某个函数,使用__attribute__((destructor))来在main函数执行之后执行某个函数。\[1\]这些属性可以用于实现一些特殊的功能或行为,比如在程序运行前后执行一些初始化或清理操作。在给函数、变量或类型添加属性时,需要按照特定的格式来设置,比如使用__attribute__((attr_list))的形式来指定属性列表。\[2\]\[3\] #### 引用[.reference_title] - *1* *3* [C语言attribute机制](https://blog.csdn.net/weixin_37867857/article/details/102940773)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [C语言再学习 -- __attribute__详解](https://blog.csdn.net/qq_29350001/article/details/129390465)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值