新闻  |   论坛  |   博客  |   在线研讨会
__attribute__((format(printf, 1, 2)));的作用
电子禅石 | 2020-08-01 00:13:36    阅读:2048   发布文章

大家可能习惯了printf家族的习惯,但是有的时候,我们可能有新的需求,C语言所带的printf家族的函数不再满足我们的需求。但强大的C语言,由stdarg.h提供了强大的字符合成和解析功能。下面,我以一个例子来给大家介绍可变参数列表的解析。

#include <stdarg.h>
#include <unistd.h>
#include <stdio.h>
#define ATTR __attribute__
static char sprint_buf[1024];
static int myprintf(char *fmt, ...) ATTR((format(printf,1,2)));
int myprintf(char *fmt, ...)
{
    va_list args;
    int n;
    va_start(args, fmt);
    n = vsprintf(sprint_buf, fmt, args);
    va_end(args);
    write(1, sprint_buf, n);
    return n;
}
int
main()
{
    char a[10] = "Misoralv";
    char b[10] = "Klose";
    int a1 = 14;
    int n = myprintf("%s %s, his WorldCup goals reach %d.", a,b,a1);
    printf("n=%d\n",n);
    return 0;
}
简单介绍:
1. __attribute__ 为编译器提供了错误检查的功能,(format(printf,1,2)) 1= format 的位置, 2为parameters 的位置,这个后缀要加在函数声明之后。

$ cat test.c1 extern void eprintf(const char *format, ...) 2 __attribute__((format(printf, 1, 2)));3 4 void foo() 5 { 6 eprintf("s=%s\n", 5); 7 8 eprintf("n=%d,%d,%d\n", 1, 2); 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
使得编译器多了一层检查,这就是__attribute__的目的。

2.va_list 用来存储可变参数表
va_start(va_list a, fmt),va_list获取fmt之后的参数列表的值, va_start的具体实现是一个宏,它的具体内容为:
#define va_start(v,l)    __builtin_va_start(v,l)
// GCC provides a large number of built-in functions other than the ones mentioned above. Some of these are for internal use in the processing of exceptions or variable-length argument lists and will not be documented here because they may change from time to time; we do not recommend general use of these functions
同理可以理解va_end(va_list a)标识参数列表结束。

在我的函数中还有没有使用到的 va_arg,它的含义是取va_list中下一个的值。接口如下:
type va_arg ( va_list ap, type ) 
type: int / double/ long /...
例子:最大值 int FindMax ( int amount, ...) { int i,val,greater; va_list vl; va_start(vl,amount); greater=va_arg(vl,int); for (i=1;i<amount;i++) { val=va_arg(vl,int); greater=(greater>val)?greater:val; } va_end(vl); return greater; }在我们的函数最为重要的是
int vsprintf (char * str, const char * format, va_list arg );

format是类似"%s %s, his WorldCup goals reach %d."的输出格式。
str是按照输出格式将arg输出的字符串
返回值为int,表述输出了多少个字符。


Klose


*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。

参与讨论
登录后参与讨论
属于自己的技术积累分享,成为嵌入式系统研发高手。
推荐文章
最近访客