__attribute__ format

本文深入解析GCC中的函数属性format(printf),解释如何使用该属性进行参数格式检查,提高代码质量。并通过实例展示了如何在程序中加入此类检查,及时发现并修正错误。

直接引入我们的主角(粗体部分):

  int
  my_printf (void *my_object, const char *my_format, ...)
                __attribute__ ((format (printf, 2, 3)));

my_printf是一个你自己写的函数,比如可能是对vsnprintf等函数进行了封装等等。粗体部分关键字“__attribute__”可以为函数声明赋属性值,其目的是让编译程序可以优化处理。

关键字“__attribute__”可以为函数(Function Attributes),变量(Variable Attributes)和结构成员(Type Attributes)赋属性。具体可以查看gcc手册(http://gcc.gnu.org/onlinedocs/)。这里用到的是函数属性,其语法为:“__attribute__ ((attribute-list))”,并置于函数声明尾部“;”之前。

format (archetype, string-index, first-to-check)

format属性告诉编译器,按照printf, scanf, strftimestrfmon的参数表格式规则对该函数的参数进行检查。“archetype”指定是哪种风格;“string-index”指定传入函数的第几个参数是格式化字符串;“first-to-check”指定从函数的第几个参数开始按上述规则进行检查。

例如:上述例子中,函数my_printf对其参数按“printf”的参数格式进行检查,my_printf的第二个参数的格式化字符串,从my_printf的第三个参数开始进行检查。

还有,在编译时只用指定了-Wformat选项,才会出现警告信息。(我们一般都是-Wall的,没问题)

这样,利用这样一个GCC的编译关键字就能在编译时对你指定的函数进行某种规则检查。赶快行动,在你的程序中加入这些,让编译器来为你做检查吧。(我在程序中加入这些,马上编译,立刻就发现一个long型变量使用%d进行格式化的错误)

引出的一个题外话:如果上述函数my_printf是一个类的成员函数,那么上述声明就应该写成:

  int
  my_printf (void *my_object, const char *my_format, ...)
                __attribute__ ((format (printf, 3, 4)));

为什么现在是34

因为类成员函数有一个隐含的参数“this”指针作为函数的第一个参数。


#include <stdio.h>
#include <stdlib.h>
//在main函数之前执行
static  __attribute__((constructor)) void before()
{
 
    printf("Hello");
}
//在main函数之后执行
static  __attribute__((destructor)) void after()
{
    printf(" World!\n");
}
int main(int args,char ** argv)
{ 	
    return EXIT_SUCCESS;
}

#include <stdarg.h>
#include <stdio.h>
#include <unistd.h>

int myprintf(const char * fmt, ...) __attribute__((format(printf, 1, 2)));

char myprintf_buf[1024];


int myprintf(const char * fmt, ...)
{
	va_list args;	
	int n;
	
	va_start(args, fmt);
	n = vsnprintf(myprintf_buf, 1024, fmt, args);
	va_end(args);

	write(1, myprintf_buf, n);	
	return n;
}

int main()
{
	myprintf("Hello, Linux %d\n", 5);
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值