C语言__attribute__机制

C语言


如果你读过Linux内核源码,那你一定经常会看到__attribute__。

struct hci_ev_si_device {
  __u16    event;
  __u16    dev_id;
} __attribute__ ((packed));

后面跟上两个括号,括号里面一般会写packed aligned unused等等。

这个语法我们在写代码的时候很少遇到,今天就来简单的了解下它的用法。

attribute翻译过来是属性的意思,所以它的作用就是用来设置函数、变量或者数据类型的属性。

下面通过代码来演示下它的书写规则。

我们都知道C语言的入口是主函数,如果想要在主函数之前或者之后执行代码,就可以使用attribute。

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

__attribute__((constructor))
void before(void)
{
    printf("this is before ...\n");
}

__attribute__((destructor))
void after(void)
{
    printf("this is after ...\n");
}

int main()
{
    printf("hellowrold\n");

    return 0;
}

定义两个普通函数,一个before,一个after,分别在函数的上面加上attribute修饰,attribute前后各有两个下划线,括号也是两个叠加在一起,参数一个是constructor,一个是destructor,翻译过来有点像C++里面的构造函数和析构函数。

编译运行程序,即使before和after没有被调用,也仍然会被执行。

root@Turbo:test# gcc test.c -o test
root@Turbo:test# ./test 
this is before ...
hellowrold
this is after ...
root@Turbo:test#

当然,attribute语法没有那么严格,即使和函数放在同一行,也可以编通过。

void __attribute__((constructor)) before(void)
{
    printf("this is before ...\n");
}

void __attribute__((destructor)) after(void)
{
    printf("this is after ...\n");
}

attribute后面的参数有很多,我们随便挑几个看下。

比如noreturn,意思就是没有返回值的意思。

随便来个函数,返回值是void,如果加上noreturn属性,编译的时候就会提示警告,因为void也属于返回值。

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

__attribute__((noreturn))
void test()
{

}

int main()
{
    return 0;
}
root@Turbo:test# gcc test.c -o test
test.c: In function ‘test’:
test.c:8:1: warning: ‘noreturn’ function does return
    8 | }
      | ^
root@Turbo:test#

所以必须在函数内部调用同样具有noreturn属性的函数,编译才能通过。

__attribute__((noreturn))
void test()
{
    exit(0);
}

再比如参数mode,用来设置整型的长度,可以是QI,一个字节,可以是HI,两个字节。

typedef unsigned int myint __attribute__((mode(QI)));

最常见的参数应该是packed,一般用于结构体后面。

正常的结构体会有字节对齐,比如这样的:

struct Test
{
    char ch;
    int id;
    char sex;
    int age;
};

在内存在中占了16个字节。
加上packed属性,就会丢掉字节对齐,该多少个字节就是多少个字节。

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

struct Test
{
    char ch; 
    int id; 
    char sex;
    int age;
}__attribute__((packed));

int main()
{
    printf("%lu\n", sizeof(struct Test));
    return 0;
}
root@Turbo:test# ./test 
10
root@Turbo:test#

当然,packed还可以换成aligned,就是指定对齐宽度。

struct Test
{
    char ch; 
    int id; 
    char sex;
    int age;
}__attribute__((aligned(32)));

最后,再看一个unused,如果你在代码中定义了静态函数但是没有调用,编译的时候编译器就会提示警告,加上unused,就能消除这个警告。

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

__attribute__((unused))
static void test()
{
}

int main()
{
    return 0;
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值