最近在修正代码警告,发现封装的打印语句不会进行参数的类型检查,而用printf却是可以的。于是上网找了下资料,学习了一下。

对于函数参数类型的检查,在gcc环境中可以使用__attribute__((format(printf,N,M)))的形式。其中N表示第几个参数是格式化字符串,M指明从第几个参数开始做检查。对于__attribute__,等有空专门学习一下再写篇文章出来。

下面是可变参数f的一个简单例子:

void my_printf(const char* fmt, ...) { #define LINE_SIZE 1024char buffer[LINE_SIZE] = {0};va_list vl;va_start(vl, fmt);vsprintf(buffer, fmt, vl);fputs(buffer, stdout);va_end(vl); }

代码不复杂,使用了va_list等几个宏和vsprintf来实现可变参数。但调用my_printf不会进行参数类型检查。测试例子如下:

void simple_test(void) {int a = 250;char* p = NULL;my_printf("hehe %d, %s\n", p, a);my_printf("ddd: %d\n");my_printf("ddd: \n", a); }

我就乱用整型、指针,甚至多参数少参数,但编译没有警告,原因就是my_printf不够严格,当然对于指针的打印,可以使用%d,但如果使用%s来打印一个整数,就会有段错误,如果在编译阶段就能看到警告,就不会等到运行时才发现,特别是当代码工程大,而打印语句在一定条件下才触发,问题就更难找了。因此,对函数的参数进行严格的检查是很有必要的。上例中,把声明改为:

void my_printf(const char* fmt, ...) __attribute__((format(printf,1,2)));

这样就解决问题了。对于上面的示例,编译会提到有警告,如下:

test.cpp: In function ‘void simple_test()’: test.cpp:32: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘char*’ test.cpp:32: warning: format ‘%s’ expects type ‘char*’, but argument 3 has type ‘int’ test.cpp:33: warning: too few arguments for format test.cpp:34: warning: too many arguments for format

使用 __attribute__((format(printf,N,M)))的函数形式基本固定,最后的参数是省略号。比如经典的API:

int printf(const char *format, ...); int fprintf(FILE *stream, const char *format, ...); int sprintf(char *str, const char *format, ...); int snprintf(char *str, size_t size, const char *format, ...); void syslog(int priority, const char *format, ...);

如果N、M指定的位置不对,编译会报错,提示:

error: format string argument not a string type

特别要说明的是在C++类中如使用 __attribute__((format(printf,N,M)))则要注意参数位置,C++默认隐藏有this指针,所以N、M的值要加1。但是类的静态成员没有this指针。附上使用C++类封装的例子:

class MyPrintf { public:// 静态成员无thisstatic void print(int level, const char* fmt, ...) __attribute__((format(printf,2,3)));// 有this指针void print(int level, int level2, const char* fmt, ...) __attribute__((format(printf,4,5))); };void MyPrintf::print(int level, const char* fmt, ...) { #define LINE_SIZE 1024char buffer[LINE_SIZE] = {0};va_list vl;va_start(vl, fmt);vsprintf(buffer, fmt, vl);printf("[%d] ", level);fputs(buffer, stdout);va_end(vl); }void MyPrintf::print(int level, int level2, const char* fmt, ...) { #define LINE_SIZE 1024char buffer[LINE_SIZE] = {0};va_list vl;va_start(vl, fmt);vsprintf(buffer, fmt, vl);printf("[%d %d] ", level, level2);fputs(buffer, stdout);va_end(vl); }

李迟 2015.4.23 周四 中午

一个可变参数类型检查的示例相关推荐

  1. 深度解析Java可变参数类型以及与数组的区别

    这篇文章主要介绍了Java方法的可变参数类型,通过实例对Java中的可变参数类型进行了较为深入的分析,需要的朋友可以参考下. Java方法中的可变参数类型是一个非常重要的概念,有着非常广泛的应用.本文 ...

  2. Java可变参数类型实例

    可变参数:         Java1.5增加了新特性:可变参数:适用于参数个数不确定,类型确定的情况,java把可变参数当做数组处理. 可变的参数类型,也称为不定参数类型.英文缩写是varargus ...

  3. python 函数参数类型检查

    在Python中,不知道函数参数类型是一个很正常的事情,特别是在一个大项目里. 我见过有些项目里,每一个函数体的前十几行都在检查参数类型,这实在是太麻烦了.而且一旦参数有改动,这部分也需要改动. 下面 ...

  4. python参数类型检查_Python中的类型检查

    本文中所有代码均运行在Python 2.7上 为什么要进行类型检查? 总所周知,Python是一门典型的动态语言,在变量定义.使用的过程中遵循duck typing,当对某一变量进行操作时才去检查它是 ...

  5. python函数参数类型检查_Python中实现参数类型检查的简单方法

    Python是一门弱类型语言,很多从C/C++转过来的朋友起初不是很适应.比如,在声明一个函数时,不能指定参数的类型.用C做类比,那就是所有参数都是void*类型!void类型强制转换在C++中被广泛 ...

  6. [转载] python 函数参数类型检查

    参考链接: Python函数参数 在Python中,不知道函数参数类型是一个很正常的事情,特别是在一个大项目里. 我见过有些项目里,每一个函数体的前十几行都在检查参数类型,这实在是太麻烦了.而且一旦参 ...

  7. C 语言的可变参数类型 stdarg

    va_list/va_start/va_arg/va_end这几个宏,都是用于函数的可变参数的. 我们来看看在vs2008中,它们是怎么定义的: 1: ///stdarg.h2: #define va ...

  8. getMethod方法getMethod(String name, Class<?>... parameterTypes)传入可变参数类型

    反射的getMethod方法getMethod(String name, Class<?>- parameterTypes) Class<?>- parameterTypes ...

  9. c语言函数参数类型检查,内联函数在编译时是否做参数类型检查?

    先说宏和函数的区别: 1. 宏做的是简单的字符串替换(注意是字符串的替换,不是其他类型参数的替换),而函数的参数的传递,参数是有数据类型的,可以是各种各样的类型. 2. 宏的参数替换是不经计算而直接处 ...

最新文章

  1. 这份Kaggle Grandmaster的图像分类训练技巧,你知道多少?
  2. 多迪将企业的Python工程师定位成哪几类?
  3. python加载shellcode免杀 简介
  4. Python爬虫对json数据解析爬取
  5. excel撤销工作表保护默认密码_我的表格我做主:Excel工作表不想被别人改动,设置一个密码保护...
  6. 怎么删除计算机c盘应用程序,如何删除C盘的垃圾文件!!
  7. Eclipse中手动清理项目缓存,
  8. java date postmax_Postman支持的几种数据类型请求方式
  9. gradle 安装_如何安装Gradle
  10. 良好的用户界面设计技巧
  11. python 三维数组_NumPy处理图像不香吗?我用Python把秋日里最美的景色做成了这种效果~...
  12. 苹果Mac图片墙制作软件:FigrCollage
  13. 微信实现双向跨境支付,将向香港用户开放内地支付服务
  14. spring-boot-starter-parent 包maven依赖报错
  15. BPM 与 SOA的演进与展望
  16. html图片与文字的排版6,HTML文字与排版
  17. 倒计时1天,六位专家周末带你解锁前端研发新姿势
  18. 安装chrome扩展插件.Crx文件时,总提示程序包无效:CRX_HEADER_INVALID
  19. Matlab使用-meshgrid函数(网格矩阵)
  20. python画美图_用python做个街拍美图手册

热门文章

  1. 华硕无双新品首爆:H45标压处理器+全球首款2.8K 120Hz OLED屏
  2. 小鹏汽车高管个人年薪超4亿?网友:超过我对金钱的认知了
  3. 任正非:华为要防止内卷 精益求精不叫内卷
  4. 俞敏洪辟谣“周末暑假不能上课”:人生已经不易 为何还要捅刀
  5. 雷军:小米11的屏幕是小米手机有史以来最贵且最好的屏幕
  6. 雷军微博正式“确认”:Redmi Note 9 5G高配版处理器就是它
  7. 神州租车:陆正耀辞任公司董事会主席及非执行董事职务
  8. 里程碑!中国移动5G信号将覆盖珠峰峰顶
  9. 嘿,来打游戏!中国电竞人才缺口达50万
  10. 旗下首发双模5G+双挖孔全面屏!Redmi K30真机谍照曝光