可变参数列表<stdarg.h>
来源:互联网 发布:百川二建考试软件 编辑:程序博客网 时间:2024/05/22 00:17
调试的错误就是编程给你最好的东西,因为在每个错误上面都标志着前进的一步。
—-By CSDN
在练习写一个简单版scanf函数,测试时出现意外错误,检查了一下,可能是对头文件里一些宏的引用出错。查了一下源代码,取了部分关键的几个宏定义:
1)va_list 宏定义
#ifndef _VA_LIST#define _VA_LISTtypedef char* va_list;#endif
2)va_argsiz(t)获取类型占用的空间长度,最小占用长度为int的整数倍
#define __va_argsiz(t) (((sizeof(t) + sizeof(int) - 1) / sizeof(int)) * sizeof(int))
3)va_start,使ap指向第一个无名参数
#ifdef __GNUC__#define va_start(ap, pN) ((ap) = ((va_list) __builtin_next_arg(pN)))#else#define va_start(ap, pN) \ ((ap) = ((va_list) (&pN) + __va_argsiz(pN))) #endif
4)清空va_list列表
#define va_end(ap) ( ap = (va_list)0 )
5)返回与当前无名参数具有相同类型和数值的值,并使ap指向下一个无名参数
#define va_arg(ap, t) (((ap) = (ap) + __va_argsiz(t)), *((t*) (void*) ((ap) - __va_argsiz(t))))
——————————————————————————————————————–
我写的读取标准输入流中的字符程序,就需要修改参数变量的值。
那么问题来了,如果参数是一个地址,如何修改地址中的值呢?其实是一样的,比如传递一个(int*)的参数进去,*((int**)(void*) ((ap) - __va_argsiz(int*))))。
这里int**是将指向void类型的指针转为指向int*的指针,再解引用,就变成了(int*)的参数。
——————————————————————————————————————–
下面是简单版的scanf函数
#include<stdio.h>#include<stdlib.h>#include<string.h>#include<stdarg.h>#define MAXWORD 50void minscanf(char *fmt,...){ va_list ap; char *p, *sval; int i, *ival; double *fval; va_start(ap, fmt); for(p = fmt; *p; p++) { char c[MAXWORD]; while(*p==' ' || *p=='\t' || *p=='\n') p++; if(*p == '%'){ while( (*c = getchar() ) == ' ' ) ; i = 0; while((c[++i] = getchar()) != ' ' && c[i]!='\n' ) ; c[i] = '\n'; switch(*++p) { case 'd': ival = va_arg(ap,int *); *ival = atoi(c); \\ ap++; break; case 'f': fval = va_arg(ap,double *) ; *fval = atof(c); \\ ap++; break; case 's': sval = va_arg(ap,char *); strcpy(sval,c); \\ ap++; break; default: continue; } } printf("\n"); } va_end(ap);}
调试过程中,操作系统给出了“SIGSEGV”信号,查了一下资料。SIG是信号名的通用前缀。SEGV是segmentationviolation(段违例)的缩写。SIGSEGV是当一个进程执行了一个无效的内存引用,或发生段错误时发送给它的信号。通常是访问了一个不可用的内存地址,或着往只读内存地址写数据。
检查了很久,才发现是ap++;这句话出错了,应该删去。
仔细想想,这种毛病在高中时代做题时就有了,惯性动作带来的后果。为使ap指向下一个位置,就直接ap++了。呵呵~
此外,写这个程序的过程中还犯了一个老毛病,变量的位置放置错误,导致不恰当的作用域,从而在循环的过程中上一次循环变量的值影响这一次。
- 可变参数列表<stdarg.h>
- 可变参数列表,stdarg
- [C语言]利用stdarg.h来实现可变参数列表
- 可变参数处理,stdarg.h
- 可变参数列表:stdarg宏
- 可变参数列表的宏和<stdarg.h>实现函数的可变参数列表
- c可变参数和stdarg.h
- stdarg.h编写可变参数函数
- 可变参数(C语言):stdarg.h
- 可变参数列表通过宏来实现(头文件stdarg.h)
- 使用varargs.h/stdarg.h 实现可变参数函数
- 用库函数stdarg.h实现函数参数的可变
- stdarg.h——用于函数接受可变参数
- CC++可变参数stdarg.h中的余数运用
- 详解stdarg.h文件(可变参数函数的操作)
- 可变参数函数stdarg
- stdarg(3) variable argument lists 可变参数列表
- stdarg Macro 关于可变参数
- XML文件读取
- Android TextView跑马灯效果与设置文字阴影
- LayoutSubviews总结
- JAVA解析XML文件(三)---JDOM方式解析
- Node.js-require() 源码解读
- 可变参数列表<stdarg.h>
- 汇总Javascript各种判断脚本(javascript经典例子)
- iOS-UIButton和UIImageView的区别
- spawn分析
- 1013. 数素数 (20)
- 慕课网 static 静态变量
- angularJS学习之路(三)---控制器
- 值栈与ognl
- Maximum Product subarray | LeetCode