A mixed example of C language variable parameter function, variable parameter macro, using void* to spread multiple parameters, and obtaining multiple data by matching the memory address and struct with this address as memory




#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;
	/*Can't take paramsFormat plus offset address to take parameters, the address stored in paramsFormat is the first address of the continuous memory area of ​​the bunch of characters, not the first address of the parameter
	  So take the address of the data storage area that points to the first address of this contiguous memory area (addressing the "root" - find the address that points to this address) */
	void* firstParamsAddress = (void*) (¶msFormat + sizeof(char));
	int currentParams = (int)firstParamsAddress;
	for(i = 0; i < strlen(paramsFormat); i++){
		if(paramsFormat[i] == '%')
			paramsLength++;
	}
	printf("Parameter length%d\n", paramsLength);
	for(i = 1; i <= strlen(paramsFormat); i++){
		if(paramsFormat[i - 1] == '%') {
			switch(paramsFormat[i]){
				case 'd':
					printf("The content of the %d parameter is: %d\n", ++j, *((int*)currentParams));
					currentParams+=sizeof(int);
					break;
				case 'f':
					printf("The content of the %d parameter is: %f\n", ++j, *((double*)currentParams));
					currentParams+=sizeof(double);
					break;
				case 'c':
					printf("The content of the %d parameter is: %c\n", ++j, ((char*)currentParams)[0]);
					currentParams+=sizeof(char*);
					break;
				case 's':
					/*The string parameter is the address that holds the integer pointing to the "first address of the character array", get the address,
					  And get the content saved in the address - the address integer of "the first address of the character array", and then convert it to a string address
					 (addressing "leaf" - address of address) */
					 /*
					 To explain again, the current currentParams points to an address ((int*)currentParams) whose content is "address" (integer),
					 So take the content of currentParams, get the address it points to (the address of the next level), (refer to *(int*)currentParams
					 This operation, because the pointed content (address) is int shape, so use (int*) to convert the address, and then add * operation in front
					 The address obtained is the first address of the continuous storage area that saves the character array (string), so it can be directly put into the printf
					 Read string from %s */
					printf("The content of the %d parameter is: %s\n", ++j, (char*)(*(int*)currentParams));
					currentParams+=sizeof(char*);
					break;
				cell 'l':
					if(paramsFormat[i+1] == 'd'){
						printf("The content of the %d parameter is: %ld\n", ++j, *(long*)currentParams);
						currentParams+=sizeof(long);
						i++;
					}
					break;
				default:
					printf("The type of the %d parameter is wrong, skipping...\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, "Variable parameter function test", 678, 678999999L, "Hahahahahaha");
	testMultiParams("%d%s%d%yyy%s", 3, "Error Case Test", 678, 678999999L, "Test");
	printf("%.2f\n", 3.1415f);
	testMultiParams("%d%s%c%f%ld%s", 3, "test", 'b', 3.1415f, 678999999L, "test");
	getchar();
	return 0;
}




Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325519231&siteId=291194637