#include "stdio.h" #include "stdlib.h" #include "string.h" #define display(flag, msg) if(flag) printf("%s\n",msg) #define new(Class) (Class*)malloc(sizeof(Class)) #define findMethodByObject(Object, Method, ARGS) Object->Method(Object, ARGS) typedef struct Test TestItem; struct Test{ char* name; void (*fun1)(TestItem *comeFromItem, void* args); void (*fun2)(TestItem *comeFromItem, void* args); }; void testFun(TestItem *comeFromItem, void* args){ printf("Get callback str:%s\n", comeFromItem->name); } void testFun2(TestItem *comeFromItem, void* args){ struct params{ char* a1; char* a2; int a3; }; int i; struct params *argsToParmas = (struct params*) args; for(i=0; i < argsToParmas->a3; i++){ printf("Get callback2 str:%s\n", argsToParmas->a1); printf("Get callback2 str:%s\n", argsToParmas->a2); } } TestItem* initAnTestObject(){ TestItem *item = new(TestItem); item->name = "I am an object\n"; item->fun1 = testFun; item->fun2 = testFun2; return item; } void testMultiParams(char *paramsFormat, ...){ int paramsLength = 0, i, j = 0; /*不能拿paramsFormat加偏移地址拿参数,paramsFormat存的地址是那堆字符的连续内存区的首地址,不是参数的首地址 所以要拿指向这个连续内存区的首地址的数据存储区的地址(向“根”寻址——找到指向这个地址的地址)*/ void* firstParamsAddress = (void*) (¶msFormat + sizeof(char)); int currentParams = (int)firstParamsAddress; for(i = 0; i < strlen(paramsFormat); i++){ if(paramsFormat[i] == '%') paramsLength++; } printf("参数长度%d\n", paramsLength); for(i = 1; i <= strlen(paramsFormat); i++){ if(paramsFormat[i - 1] == '%') { switch(paramsFormat[i]){ case 'd': printf("第%d参数内容是:%d\n", ++j, *((int*)currentParams)); currentParams+=sizeof(int); break; case 'f': printf("第%d参数内容是:%f\n", ++j, *((double*)currentParams)); currentParams+=sizeof(double); break; case 'c': printf("第%d参数内容是:%c\n", ++j, ((char*)currentParams)[0]); currentParams+=sizeof(char*); break; case 's': /*字符串形参数是保存着指向一个“字符数组首地址”这个整数的地址,取得该地址, 并取得地址中保存了的内容——“字符数组首地址”这个地址整数,然后转为字符串地址 (向“叶”寻址——地址的地址)*/ /* 再解释一下,当前的currentParams指向一个内容为“地址”(整数)的地址((int*)currentParams), 所以取currentParams的内容,就取得其指向的地址(下一级的地址),(指*(int*)currentParams的 这个操作,因为指向的内容(地址)是int形,所以要用(int*)转化一下该地址,再在前面加上*操作 符取得其内容)取得的这个地址是保存字符数组(串)的连续存储区首地址,因此可以直接放进printf的 %s中读出字符串*/ printf("第%d参数内容是:%s\n", ++j, (char*)(*(int*)currentParams)); currentParams+=sizeof(char*); break; case 'l': if(paramsFormat[i+1] == 'd'){ printf("第%d参数内容是:%ld\n", ++j, *(long*)currentParams); currentParams+=sizeof(long); i++; } break; default: printf("第%d参数类型标记错误,正在跳过...\n", j+1); while(paramsFormat[++i] != '%'); currentParams+=sizeof(void*); ++j; break; } } } } int main(){ TestItem *item = initAnTestObject(); display(1, item->name); findMethodByObject(item, fun1, NULL); struct params{ char* arg1; char* arg2; int arg3; }; struct params paramExample; paramExample.arg1 = "Param1\n"; paramExample.arg2 = "Param2\n"; paramExample.arg3 = 3; findMethodByObject(item, fun2, (void*)¶mExample); testMultiParams("%d", 123); testMultiParams("%d%d", 123, 345); testMultiParams("%d%s%d", 123, "asdasdasd", 678); testMultiParams("%d%s%d%ld%s", 123, "变参函数测试", 678, 678999999L, "哈哈哈哈哈哈"); testMultiParams("%d%s%d%yyy%s", 3, "错误情况测试", 678, 678999999L, "测试"); printf("%.2f\n", 3.1415f); testMultiParams("%d%s%c%f%ld%s", 3, "测试", 'b', 3.1415f, 678999999L, "测试"); getchar(); return 0; }
一种C语言变参函数、变参宏、利用void*传播多个参数、通过内存地址和struct匹配这个地址做内存而获得多个数据的混合例子
猜你喜欢
转载自blog.csdn.net/cjzjolly/article/details/78792044
今日推荐
周排行