概述
2.__attribute__ noreturn
3.__attribute__ const
4.__attribute__ weak
5.__attribute__ constructor
6.__attribute__ destructor
__attribute__ format
This __attribute__ allows assigning printf-like or scanf-like characteristics to the declared function, and this enables the compiler to check the format string against the parameters provided throughout the code. This is exceptionally helpful in tracking down hard-to-find bugs.
There are two flavors:
- __attribute__((format(printf,m,n)))
- __attribute__((format(scanf,m,n)))
but in practice we use the first one much more often.
The (m) is the number of the "format string" parameter, and (n) is the number of the first variadic parameter. To see some examples:
/* like printf() but to standard error only */ extern void eprintf(const char *format, ...) __attribute__((format(printf, 1, 2))); /* 1=format 2=params */ /* printf only if debugging is at the desired level */ extern void dprintf(int dlevel, const char *format, ...) __attribute__((format(printf, 2, 3))); /* 2=format 3=params */
With the functions so declared, the compiler will examine the argument lists
$ cat test.c 1 extern void eprintf(const char *format, ...) 2 __attribute__((format(printf, 1, 2))); 3 4 void foo() 5 { 6 eprintf("s=%sn", 5); /* error on this line */ 7 8 eprintf("n=%d,%d,%dn", 1, 2); /* error on this line */ 9 } $ cc -Wall -c test.c test.c: In function `foo': test.c:6: warning: format argument is not a pointer (arg 2) test.c:8: warning: too few arguments for format
Note that the "standard" library functions - printf and the like - are already understood by the compiler by default.
__attribute__ noreturn
This attribute tells the compiler that the function won't ever return, and this can be used to suppress errors about code paths not being reached. The C library functions abort() and exit() are both declared with this attribute:
extern void exit(int) __attribute__((noreturn)); extern void abort(void) __attribute__((noreturn));
Once tagged this way, the compiler can keep track of paths through the code and suppress errors that won't ever happen due to the flow of control never returning after the function call.
In this example, two nearly-identical C source files refer to an "exitnow()" function that never returns, but without the __attribute__ tag, the compiler issues a warning. The compiler is correct here, because it has no way of knowing that control doesn't return.
$ cat test1.c extern void exitnow(); int foo(int n) { if ( n > 0 ) { exitnow(); /* control never reaches this point */ } else return 0; } $ cc -c -Wall test1.c test1.c: In function `foo': test1.c:9: warning: this function may return with or without a value
But when we add __attribute__, the compiler suppresses the spurious warning:
$ cat test2.c extern void exitnow() __attribute__((noreturn)); int foo(int n) { if ( n > 0 ) exitnow(); else return 0; } $ cc -c -Wall test2.c no warnings!
__attribute__ const
This attribute marks the function as considering only its numeric parameters. This is mainly intended for the compiler to optimize away repeated calls to a function that the compiler knows will return the same value repeatedly. It applies mostly to math functions that have no static state or side effects, and whose return is solely determined by the inputs.
In this highly-contrived example, the compiler normally must call the square() function in every loop even though we know that it's going to return the same value each time:
extern int square(int n) __attribute__((const)); ... for (i = 0; i < 100; i++ ) { total += square(5) + i; }
By adding __attribute__((const)), the compiler can choose to call the function just once and cache the return value.
In virtually every case, const can't be used on functions that take pointers, because the function is not considering just the function parameters but also the data the parameters point to, and it will almost certainly break the code very badly in ways that will be nearly impossible to track down.
Furthermore, the functions so tagged cannot have any side effects or static state, so things like getchar() or time() would behave very poorly under these circumstances.
Putting them together
Multiple __attributes__ can be strung together on a single declaration, and this is not uncommon in practice. You can either use two separate __attribute__s, or use one with a comma-separated list:
/* send printf-like message to stderr and exit */ extern void die(const char *format, ...) __attribute__((noreturn)) __attribute__((format(printf, 1, 2))); /*or*/ extern void die(const char *format, ...) __attribute__((noreturn, format(printf, 1, 2)));
If this is tucked away safely in a library header file, all programs that call this function receive this checking.
Compatibility with non-GNU compilers
Fortunately, the __attribute__ mechanism was cleverly designed in a way to make it easy to quietly eliminate them if used on platforms other than GNU C. Superficially, __attribute__ appears to have multiple parameters (which would typically rule out using a macro), but the two sets of parentheses effectively make it a single parameter, and in practice this works very nicely.
/* If we're not using GNU C, elide __attribute__ */ #ifndef __GNUC__ # define __attribute__(x) /*NOTHING*/ #endif
Note that __attribute__ applies to function declarations, not definitions, and we're not sure why this is. So when defining a function that merits this treatment, an extra declaration must be used (in the same file):
/* function declaration */ void die(const char *format, ...) __attribute__((noreturn)) __attribute__((format(printf,1,2))); void die(const char *format, ...) { /* function definition */ }
以上原文http://www.unixwiz.net/techtips/gnu-c-attributes.html
__attribute__ constructor
__attribute__ destructor
#include <stdio.h>
#include <stdlib.h>
static void start(void) __attribute__ ((constructor));
static void stop(void) __attribute__ ((destructor));
int
main(int argc, char *argv[])
{
printf("start == %pn", start);
printf("stop == %pn", stop);
exit(EXIT_SUCCESS);
}
void
start(void)
{
printf("hello world!n");
}
void
stop(void)
{
printf("goodbye world!n");
}
__attribute__ ((weak))
While playing with glibc I noticed one interesting technique. It is
based on gcc's extension that allows you to declare weak symbols. In
essence it works like this:
{
if (weak_f)
{
weak_f ();
}
}
When you link such code ld won't complain if weak_f is unresolved.
Plus you can check at run-time if symbol has been resolved as shown
above.
you can make some code thread-safe on-demand. You compile this code
once and depending on kind of application it is used in it automatically
becomes multi-threaded or single-threaded:
pthread_create (pthread_t*,
const pthread_attr_t*,
void* (*)(void*),
void*) __attribute__ ((weak));
pthread_mutex_init (pthread_mutex_t*,
const pthread_mutexattr_t*) __attribute__ ((weak));
pthread_mutex_lock (pthread_mutex_t*) __attribute__ ((weak));
pthread_mutex_unlock (pthread_mutex_t*) __attribute__ ((weak));
pthread_mutex_destroy (pthread_mutex_t*) __attribute__ ((weak));
class foo
{
public:
{
if (pthread_create) pthread_mutex_init (&m_, 0);
}
~foo ()
{
if (pthread_create) pthread_mutex_destroy (&m_);
}
bar ()
{
if (pthread_create) pthread_mutex_lock (&m_);
}
pthread_mutex_t m_;
};
Now if you link your code with libpthread, foo is automatically
multi-thread-safe. If you don't then all the calls to mutex API
are skipped.
is used by both kinds of applications.
高级功能
* unused
78: #define __init __attribute__ ((__section__ (".text.init")))
79: #define __exit __attribute__ ((unused, __section__(".text.exit")))
80: #define __initdata __attribute__ ((__section__ (".data.init")))
81: #define __exitdata __attribute__ ((unused, __section__ (".data.exit")))
82: #define __initsetup __attribute__ ((unused,__section__ (".setup.init")))
83: #define __init_call __attribute__ ((unused,__section__ (".initcall.init")))
84: #define __exit_call __attribute__ ((unused,__section__ (".exitcall.exit")))
294: struct i387_fxsave_struct {
295: unsigned short cwd;
296: unsigned short swd;
297: unsigned short twd;
298: unsigned short fop;
299: long fip;
300: long fcs;
301: long foo;
......
308: } __attribute__ ((aligned (16)));
51: struct Xgt_desc_struct {
52: unsigned short size;
53: unsigned long address __attribute__((packed));
54: };
当前函数名
98: void ext2_update_dynamic_rev(struct super_block *sb)
99: {
100: struct ext2_super_block *es = EXT2_SB(sb)->s_es;
101:
102: if (le32_to_cpu(es->s_rev_level) > EXT2_GOOD_OLD_REV)
103: return;
104:
105: ext2_warning(sb, __FUNCTION__,
106: "updating to rev %d because of new feature flag, "
107: "running e2fsck is recommended",
108: EXT2_DYNAMIC_REV);
内建函数
437: printk(KERN_ERR "schedule_timeout: wrong timeout "
438: "value %lx from %pn", timeout,
439: __builtin_return_address(0));
249: #define test_bit(nr,addr)
250: (__builtin_constant_p(nr) ?
251: constant_test_bit((nr),(addr)) :
252: variable_test_bit((nr),(addr)))
13: #define likely(x) __builtin_expect((x),1)
14: #define unlikely(x) __builtin_expect((x),0)
++++ kernel/sched.c
564: if (unlikely(in_interrupt())) {
565: printk("Scheduling in interruptn");
566: BUG();
567: }
上一篇:[转]再谈javascript面向对象编程
下一篇:一个令人傻眼的错误(error: expected initializer before )
- github入门教程
- 一些关键字--volatile
- PMP总结之质量管理
- 移植mjpg-streamer
- openwrt下摄像头测试总结...
- test123
- 编写安全代码——小心有符号数...
- 使用openssl api进行加密解密...
- 一段自己打印自己的c程序...
- sql relay的c++接口
- 系统提供的库函数存在内存泄漏...
- 初学UNIX环境高级编程的,关于...
- chinaunix博客什么时候可以设...
- 一个访问量较大网站的服务器。...
- 收音机驱动与v4l2架构的关系,...
最后
以上就是疯狂爆米花为你收集整理的__attribute__使用的一些总结__attribute__ format__attribute__ noreturn__attribute__ constPutting them togetherCompatibility with non-GNU compilers的全部内容,希望文章能够帮你解决__attribute__使用的一些总结__attribute__ format__attribute__ noreturn__attribute__ constPutting them togetherCompatibility with non-GNU compilers所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复