一个可变参数类型检查的示例
最近在修正代码警告,发现封装的打印语句不会进行参数的类型检查,而用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 周四 中午
一个可变参数类型检查的示例相关推荐
- 深度解析Java可变参数类型以及与数组的区别
这篇文章主要介绍了Java方法的可变参数类型,通过实例对Java中的可变参数类型进行了较为深入的分析,需要的朋友可以参考下. Java方法中的可变参数类型是一个非常重要的概念,有着非常广泛的应用.本文 ...
- Java可变参数类型实例
可变参数: Java1.5增加了新特性:可变参数:适用于参数个数不确定,类型确定的情况,java把可变参数当做数组处理. 可变的参数类型,也称为不定参数类型.英文缩写是varargus ...
- python 函数参数类型检查
在Python中,不知道函数参数类型是一个很正常的事情,特别是在一个大项目里. 我见过有些项目里,每一个函数体的前十几行都在检查参数类型,这实在是太麻烦了.而且一旦参数有改动,这部分也需要改动. 下面 ...
- python参数类型检查_Python中的类型检查
本文中所有代码均运行在Python 2.7上 为什么要进行类型检查? 总所周知,Python是一门典型的动态语言,在变量定义.使用的过程中遵循duck typing,当对某一变量进行操作时才去检查它是 ...
- python函数参数类型检查_Python中实现参数类型检查的简单方法
Python是一门弱类型语言,很多从C/C++转过来的朋友起初不是很适应.比如,在声明一个函数时,不能指定参数的类型.用C做类比,那就是所有参数都是void*类型!void类型强制转换在C++中被广泛 ...
- [转载] python 函数参数类型检查
参考链接: Python函数参数 在Python中,不知道函数参数类型是一个很正常的事情,特别是在一个大项目里. 我见过有些项目里,每一个函数体的前十几行都在检查参数类型,这实在是太麻烦了.而且一旦参 ...
- C 语言的可变参数类型 stdarg
va_list/va_start/va_arg/va_end这几个宏,都是用于函数的可变参数的. 我们来看看在vs2008中,它们是怎么定义的: 1: ///stdarg.h2: #define va ...
- getMethod方法getMethod(String name, Class<?>... parameterTypes)传入可变参数类型
反射的getMethod方法getMethod(String name, Class<?>- parameterTypes) Class<?>- parameterTypes ...
- c语言函数参数类型检查,内联函数在编译时是否做参数类型检查?
先说宏和函数的区别: 1. 宏做的是简单的字符串替换(注意是字符串的替换,不是其他类型参数的替换),而函数的参数的传递,参数是有数据类型的,可以是各种各样的类型. 2. 宏的参数替换是不经计算而直接处 ...
最新文章
- 这份Kaggle Grandmaster的图像分类训练技巧,你知道多少?
- 多迪将企业的Python工程师定位成哪几类?
- python加载shellcode免杀 简介
- Python爬虫对json数据解析爬取
- excel撤销工作表保护默认密码_我的表格我做主:Excel工作表不想被别人改动,设置一个密码保护...
- 怎么删除计算机c盘应用程序,如何删除C盘的垃圾文件!!
- Eclipse中手动清理项目缓存,
- java date postmax_Postman支持的几种数据类型请求方式
- gradle 安装_如何安装Gradle
- 良好的用户界面设计技巧
- python 三维数组_NumPy处理图像不香吗?我用Python把秋日里最美的景色做成了这种效果~...
- 苹果Mac图片墙制作软件:FigrCollage
- 微信实现双向跨境支付,将向香港用户开放内地支付服务
- spring-boot-starter-parent 包maven依赖报错
- BPM 与 SOA的演进与展望
- html图片与文字的排版6,HTML文字与排版
- 倒计时1天,六位专家周末带你解锁前端研发新姿势
- 安装chrome扩展插件.Crx文件时,总提示程序包无效:CRX_HEADER_INVALID
- Matlab使用-meshgrid函数(网格矩阵)
- python画美图_用python做个街拍美图手册
热门文章
- 华硕无双新品首爆:H45标压处理器+全球首款2.8K 120Hz OLED屏
- 小鹏汽车高管个人年薪超4亿?网友:超过我对金钱的认知了
- 任正非:华为要防止内卷 精益求精不叫内卷
- 俞敏洪辟谣“周末暑假不能上课”:人生已经不易 为何还要捅刀
- 雷军:小米11的屏幕是小米手机有史以来最贵且最好的屏幕
- 雷军微博正式“确认”:Redmi Note 9 5G高配版处理器就是它
- 神州租车:陆正耀辞任公司董事会主席及非执行董事职务
- 里程碑!中国移动5G信号将覆盖珠峰峰顶
- 嘿,来打游戏!中国电竞人才缺口达50万
- 旗下首发双模5G+双挖孔全面屏!Redmi K30真机谍照曝光