概述
目录
- 一 介绍
- 二 语法
- 三 函数属性
- 1 format
- 2 noreturn
- 3 const
- 4 noinline
- 5 always_inline
- 6 pure
- 7 nothrow
- 8 sentinel
- 9 format_arg
- 10 no_instrument_function
- 11 section
- 12 constructor
- 13 destructor
- 14 used
- 15 unused
- 16 deprecated
- 17 weak
- 18 malloc
- a19 lias
- 20 warn_unused_result
- 21 nonnull
- 四 类型属性(Type Attributes)
- 1 aligned
- 2 packed
- 3 transparent_union
- 4 deprecated
- 5 may_alias
- 6 constructor_destructor
- 五 变量属性(Variable Attribute)
- 六 Clang特有的
- 七 demo
一 介绍
GNU C的一大特色就是 __attribute__
机制。可以设置函数属性(Function Attribute)、变量属性(Variable Attribute) 和类型属性(Type Attribute)。
关键字 __attribute__
也可以对结构体(struct)或共用体(union)进行属性设置。大致有六个参数值可以被设定,即:aligned
,packed
,transparent_union
,unused
,deprecated
和may_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=%dn",6);
myprint("i=%sn",6);
myprint("i=%sn","abc");
myprint("%s,%d,%dn",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=%dn",total);
return 0;
}
4 noinline
5 always_inline
6 pure
7 nothrow
8 sentinel
9 format_arg
10 no_instrument_function
11 section
12 constructor
13 destructor
14 used
15 unused
16 deprecated
17 weak
18 malloc
a19 lias
20 warn_unused_result
21 nonnull
四 类型属性(Type Attributes)
1 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)=%dn",sizeof(int),sizeof(short),sizeof(char));
printf("pp=%d,qq=%d n", sizeof(pp),sizeof(qq));
return 0;
}
2 packed
3 transparent_union
4 deprecated
5 may_alias
6 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 == %pn", start);
printf("stop == %pn", 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
最后
以上就是迷人豆芽为你收集整理的C语言__attribute__的全部内容,希望文章能够帮你解决C语言__attribute__所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复