C语言函数的变参实用与分析
实现变参传递的关键是:
传入参数在内存中是连续分布的。
#define va_list void* #define va_arg(arg, type) *(type*)arg; arg = (char*)arg + sizeof(type); #define va_start(arg, start) arg = (va_list)(((char*)&(start)) + sizeof(start)) #define va_end(arg) arg = (void*)0
这四个宏其实是c语言定义好的在stdarg.h中。
通过va_start(arg, start)传入第一个参数以确定后面参数的地址。
va_arg(arg, type)取出arg的值,并将地址指向下一个
#include <stdio.h> #define va_list void* #define va_arg(arg, type) *(type*)arg; arg = (char*)arg + sizeof(type); #define va_start(arg, start) arg = (va_list)(((char*)&(start)) + sizeof(start)) #define va_end(arg) arg = (void*)0 int sum(int nr, ...) { int i = 0; int result = 0; va_list arg = NULL;///不定类型指针 va_start(arg, nr);//让指针指向第二个参数地址 for(i = 0; i < nr; i++) { result += va_arg(arg, int); } va_end(arg); return result; } int main(int argc, char* argv[]) { printf("%d\n", sum(4, 100,100,100,100)); printf("%d\n", sum(3, 200, 200, 200)); return 0; }
#include <stdio.h> #include <stdlib.h> #include <stdarg.h> /* #define va_list void* #define va_arg(arg, type) *(type*)arg; arg = (char*)arg + sizeof(type); #define va_start(arg, start) arg = (va_list)(((char*)&(start)) + sizeof(start)) 这些在stdarg.h中定义过 */ void printf_diy(char *fmt,...) { va_list arg; //定义一个不定类型指针 char c; va_start(arg, fmt); //arg指向下一个参数 do { c = *fmt; if(c != '%'){ putchar(c); //输出 } else { fmt++; switch(*fmt) { case 'd': printf("%d", *((int*)arg)); break; case 'x': printf("%#x", *((int*)arg)); break; case 'f': printf("%f", *((float*)arg)); default: break; } va_arg(arg,int); } ++fmt; } while (*fmt != '\0'); va_end(arg); return; } int main(int argc, char **argv) { int i = 1234; int j = 5678; float f = 13.9; printf_diy("i = %d\n", i); printf_diy("j = %d\n", j); printf_diy("f = %f\n", f); return 0; }