C语言__attribute__

一 介绍

  GNU C的一大特色就是__attribute__机制。可以设置函数属性(Function Attribute)变量属性(Variable Attribute)类型属性(Type Attribute)
  关键字__attribute__也可以对结构体(struct)或共用体(union)进行属性设置。大致有六个参数值可以被设定,即:alignedpackedtransparent_unionunuseddeprecatedmay_alias

二 语法

  __attribute__语法格式为:__attribute__((attribute-list))
  在使用__attribute__参数时,你也可以在参数的前后都加上“__”(两个下划线),例如,使用__aligned__而不是aligned,这样,你就可以在相应的头文件里使用它而不用关心头文件里是否有重名的宏定义。

三 函数属性

  函数属性可以帮助开发者把一些特性添加到函数声明中,从而可以使编译器在错误检查方面的功能更强大。__attribute__机制也很容易同非GNU应用程序做到兼容之功效。GNU CC需要使用–Wall编译器来击活该功能,这是控制警告信息的一个很好的方式。

1 format

  作用:该__attribute__属性可以给被声明的函数加上类似printf或者scanf的特征,它可以使编译器检查函数声明和函数实际调用参数之间的格式化字符串是否匹配。该功能十分有用,尤其是处理一些很难发现的bug。
  语法:format(archetype, string-index, first-to-check)
  format属性告诉编译器,按照printf,scanf,strftime或strfmon的参数表格式规则对该函数的参数进行检查。“archetype”指定是哪种风格;“string-index”指定传入函数的第几个参数是格式化字符串;“first-to-check”指定从函数的第几个参数开始按上述规则进行检查。
  具体使用:__attribute__((format(printf,m,n)))__attribute__((format(scanf,m,n)))
  其中参数m与n的含义为:m:第几个参数为格式化字符串(format string);n:参数集合中的第一个,即参数“…”里的第一个参数在函数参数总数排在第几,注意,有时函数参数里还有“隐身”的。

//m=1;n=2
extern void myprint(const char *format,...) __attribute__((format(printf,1,2)));
//m=2;n=3
extern void myprint(int l,const char *format,...) __attribute__((format(printf,2,3)));
//需要特别注意的是,如果myprint是一个函数的成员函数,那么m和n的值可有点“悬乎”了,例如:
//m=3;n=4
extern void myprint(int l,const char *format,...) __attribute__((format(printf,3,4)));
//其原因是,类成员函数的第一个参数实际上一个“隐身”的“this”指针。
//format-myprintf.c
#include <stdio.h>
#include <stdarg.h>
 
#ifdef ON
	//告诉编译器以printf的方式去检查该函数
	extern void myprint(const char *format,...) __attribute__((format(printf,1,2)));
#else
	extern void myprint(const char *format,...);
#endif
 
void test()
{
    myprint("i=%d\n",6);
    myprint("i=%s\n",6);
    myprint("i=%s\n","abc");
    myprint("%s,%d,%d\n",1,2);
}
 
 
//gcc -Wall format-myprintf.c -D ON
//gcc -Wall format-myprintf.c 
 
int main()
{
    test();
    return 0;
}

  注意:默认情况下,编译器是能识别类似printf的“标准”库函数

2 noreturn

  该属性通知编译器函数从不返回值,当遇到类似函数需要返回值而却不可能运行到返回值处就已经退出来的情况,该属性可以避免出现错误信息。C库函数中的abort()和exit()的声明格式就采用了这种格式,如下所示:
extern void exit(int) __attribute__((noreturn));
extern void abort(void) __attribute__((noreturn));

//noreturn.c
#include <stdio.h>
#include <stdarg.h>
 
 
#ifdef ON
    extern void myexit() __attribute__((noreturn));
#else
    extern void myexit() ;
#endif
 
int test(int n)
{
    if ( n > 0 )
    {
        myexit();
        /* 程序不可能到达这里*/
    }
    else
        return 0;
}
//https://gcc.gnu.org/onlinedocs/gcc-4.0.0/gcc/Function-Attributes.html
//__attribute__ 告诉编译器做额外的事情。
 
//编译对比
//gcc -Wall noreturn.c -D ON
//gcc -Wall noreturn.c
int main()
{
    test(3);
    return 0;
}

3 const

  该属性只能用于带有数值类型参数的函数上。当重复调用带有数值参数的函数时,由于返回值是相同的,所以此时编译器可以进行优化处理,除第一次需要运算外,其它只需要返回第一次的结果就可以了,进而可以提高效率。该属性主要适用于没有静态状态(static state)和副作用的一些函数,并且返回值仅仅依赖输入的参数。

//const.c
#include <stdio.h>
#include <stdarg.h>
 
 
#ifdef ON
    extern int square(int n) __attribute__((const));
 
#else
    extern int square(int n);
#endif
 
//编译对比
//gcc -Wall const.c -D ON
//gcc -Wall const.c
int main()
{
    int total=0;
    int i=0;
    for (i = 0; i < 100; i++ )
    {
            total += square(5) + i;
    }
    printf("total=%d\n",total);
    return 0;
}

noinline

always_inline

pure

nothrow

sentinel

format_arg

no_instrument_function

section

constructor

destructor

used

unused

deprecated

weak

malloc

alias

warn_unused_result

nonnull

  
  

四 类型属性(Type Attributes)

aligned

//aligned.c
#include <stdio.h>
#include <stdarg.h>
 
#ifdef ON
//关键字__attribute__也可以对结构体(struct)或共用体(union)进行属性设置。大致有六个参数值可以被设定,
//即:aligned, packed, transparent_union, unused, deprecated 和 may_alias。
struct p
{
    int a;
    char b;
    char c;
}__attribute__((aligned(4))) pp;
 
struct q
{
    int a;
    char b;
    struct p qn;
    char c;
}__attribute__((aligned(8))) qq;
 
#else
struct p
{
    int a;
    char b;
    char c;
} pp;
 
struct q
{
    int a;
    char b;
    struct p qn;
    char c;
} qq;
#endif
 
 
//__attribute__修饰变量属性(Variable Attribute)
struct test
{
    char a;
    int x[2] __attribute__ ((packed));
};
 
 
//gcc -Wall aligned.c -D ON -o a2
//gcc -Wall aligned.c -o a1
int main()
{
    printf("sizeof(int)=%d,sizeof(short)=%d.sizeof(char)=%d\n",sizeof(int),sizeof(short),sizeof(char));
    printf("pp=%d,qq=%d \n", sizeof(pp),sizeof(qq));
    return 0;
}

packed

transparent_union

deprecated

may_alias

constructor_destructor

//constructor_destructor.c
#include <stdio.h>
#include <stdarg.h>
 
 
#ifdef ON
static void start(void) __attribute__ ((constructor));
static void stop(void) __attribute__ ((destructor));
#else
static void start(void);
static void stop(void);
#endif
 
void start(void)
{
    printf("hello world!\n");
}
void stop(void)
{
    printf("goodbye world!\n");
}
 
//编译运行对比
//gcc -Wall noreturn.c -D ON
//gcc -Wall noreturn.c
int main(int argc, char *argv[])
{
    printf("start == %p\n", start);
    printf("stop == %p\n", stop);
    return 0;
}

  
  

五 变量属性(Variable Attribute)

  
  

六 Clang特有的

  • availability
  • overloadable

七 demo

#include <stdio.h>
#include <stdarg.h>
 
 
#ifdef ON
 
extern "C" int
pthread_create (pthread_t*,
                const pthread_attr_t*,
                void* (*)(void*),
                void*) __attribute__ ((weak));
 
extern "C" int
pthread_mutex_init (pthread_mutex_t*,
                    const pthread_mutexattr_t*) __attribute__ ((weak));
 
extern "C" int
pthread_mutex_lock (pthread_mutex_t*) __attribute__ ((weak));
 
extern "C" int
pthread_mutex_unlock (pthread_mutex_t*) __attribute__ ((weak));
 
extern "C" int
pthread_mutex_destroy (pthread_mutex_t*) __attribute__ ((weak));
 
#else
extern "C" int
pthread_create (pthread_t*,
                const pthread_attr_t*,
                void* (*)(void*),
                void*);
extern "C" int
pthread_mutex_init (pthread_mutex_t*,
                    const pthread_mutexattr_t*);
 
extern "C" int
pthread_mutex_lock (pthread_mutex_t*);
 
extern "C" int
pthread_mutex_unlock (pthread_mutex_t*);
 
extern "C" int
pthread_mutex_destroy (pthread_mutex_t*);
 
#endif
 
#define __init         __attribute__ ((__section__ (".text.init")))
#define __exit          __attribute__ ((unused, __section__(".text.exit")))
#define __initdata      __attribute__ ((__section__ (".data.init")))
#define __exitdata      __attribute__ ((unused, __section__ (".data.exit")))
#define __initsetup     __attribute__ ((unused,__section__ (".setup.init")))
#define __init_call     __attribute__ ((unused,__section__ (".initcall.init")))
#define __exit_call     __attribute__ ((unused,__section__ (".exitcall.exit")))
 
extern void foobar (void) __attribute__ ((section ("bar")));
 
 
void add(int a,int b) __attribute__ ((visibility ("protected")));
 
void sub(int a,int b) __attribute__ ((visibility ("hidden")));
 
//关键字__attribute__ 也可以对结构体(struct )或共用体(union )进行属性设置。大致有六个参数值可以被设定,
//即:aligned, packed, transparent_union, unused, deprecated 和 may_alias 。
struct STudent{
 
    int age;
    char name[10] __attribute__ ((aligned(8)));
};
 
//https://gcc.gnu.org/onlinedocs/gcc-4.0.0/gcc/Function-Attributes.html#Function-Attributes
int old_fn () __attribute__ ((deprecated));
 
void f () __attribute__ ((weak, alias ("__f")));
 
void mul() __attribute__ ((dllexport));
void mul2() __attribute__ ((dllimport));
 
extern char * my_dgettext (char *my_domain, const char *my_format)  __attribute__ ((format_arg (2)));
 
void f2 () __attribute__ ((interrupt ("IRQ")));
 
//Use naked attribute on the ARM, AVR, C4x and IP2K ports to indicate that the specified function does not need prologue/
//epilogue sequences generated by the compiler.It is up to the programmer to provide these sequences.
void mydiv() __attribute__ ((naked));
 
void mydiv2() __attribute__ ((noinline));
 
 
__attribute__ ((noinline,__annotate__(("nofcf"))))
__attribute__ ((noinline,__annotate__(("nocxf"))))
__attribute__ ((noinline,__annotate__(("nosac")))) void demo();
 
 
//编译对比
//gcc -Wall weak.c -D ON
//gcc -Wall weak.c
int main()
{
 
    return 0;
}

https://blog.csdn.net/weixin_33770878/article/details/92129273?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task


发布了67 篇原创文章 · 获赞 26 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/essity/article/details/104694694