user-0 提问: 如何在C语言中动态调用函数？

回复:
user: user-1
content: 看my_sum源码，这个数必须你指定，如果指定有误，前后不匹配，出了问题，自己负责。

user: user-0
content: 引用 7 楼 zhangxiangDavaid 的回复:[quote=引用 5 楼 super_miker 的回复:] [quote=引用 3 楼 zhangxiangDavaid 的回复:] [quote=引用 2 楼 super_miker 的回复:] [quote=引用 1 楼 zhangxiangDavaid 的回复:] my_sum这种写法叫可变参数函数：http://blog.csdn.net/zhangxiangdavaid/article/details/38278249 依据my_sum的参数类型，你是不可能把array，传递过去的，不过可以这样调用：  int my_sum(int n, ...) { 	int res = 0; 	va_list va; 	va_start(va, n); 	do { 		res += va_arg(va, int); 	} while (--n); 	va_end(va); 	return res; } int main(void) { 	printf("%d\n", my_sum(2, 1, 2)); 	printf("%d\n", my_sum(3, 1, 2, 3)); 	printf("%d\n", my_sum(4, 1, 2, 3, 4));  	return 0; } //3 //6 //10   问题是n只能在运行时确定，而且数值范围未知。。。[/quote] 在C语言中，可变参数函数是这样使用的：第一个参数指定后面可变参数的个数。 [/quote]  第一个参数确实是个数啊，但是个数是在运行时确定的[/quote]  这个数需要你指定。 [/quote]  这个数是从标准输入获得的。。。

user: user-1
content: 引用 5 楼 super_miker 的回复:[quote=引用 3 楼 zhangxiangDavaid 的回复:] [quote=引用 2 楼 super_miker 的回复:] [quote=引用 1 楼 zhangxiangDavaid 的回复:] my_sum这种写法叫可变参数函数：http://blog.csdn.net/zhangxiangdavaid/article/details/38278249 依据my_sum的参数类型，你是不可能把array，传递过去的，不过可以这样调用：  int my_sum(int n, ...) { 	int res = 0; 	va_list va; 	va_start(va, n); 	do { 		res += va_arg(va, int); 	} while (--n); 	va_end(va); 	return res; } int main(void) { 	printf("%d\n", my_sum(2, 1, 2)); 	printf("%d\n", my_sum(3, 1, 2, 3)); 	printf("%d\n", my_sum(4, 1, 2, 3, 4));  	return 0; } //3 //6 //10   问题是n只能在运行时确定，而且数值范围未知。。。[/quote] 在C语言中，可变参数函数是这样使用的：第一个参数指定后面可变参数的个数。 [/quote]  第一个参数确实是个数啊，但是个数是在运行时确定的[/quote]  这个数需要你指定。

user: user-0
content: 引用 4 楼 user-4 的回复://enter n array = (int *) malloc(sizeof(int) * n); // enter array int temp = 0; for(int i = 0; i < n; i++) { temp = my_sum(2, temp, array[i]); } 引用 4 楼 user-4 的回复://enter n array = (int *) malloc(sizeof(int) * n); // enter array int temp = 0; for(int i = 0; i < n; i++) { temp = my_sum(2, temp, array[i]); } 你说的好有道理，但实际中用的是一个函数指针，后面的参数也不是int类型而是一种指针类型。。。

user: user-0
content: 引用 3 楼 zhangxiangDavaid 的回复:[quote=引用 2 楼 super_miker 的回复:] [quote=引用 1 楼 zhangxiangDavaid 的回复:] my_sum这种写法叫可变参数函数：http://blog.csdn.net/zhangxiangdavaid/article/details/38278249 依据my_sum的参数类型，你是不可能把array，传递过去的，不过可以这样调用：  int my_sum(int n, ...) { 	int res = 0; 	va_list va; 	va_start(va, n); 	do { 		res += va_arg(va, int); 	} while (--n); 	va_end(va); 	return res; } int main(void) { 	printf("%d\n", my_sum(2, 1, 2)); 	printf("%d\n", my_sum(3, 1, 2, 3)); 	printf("%d\n", my_sum(4, 1, 2, 3, 4));  	return 0; } //3 //6 //10   问题是n只能在运行时确定，而且数值范围未知。。。[/quote] 在C语言中，可变参数函数是这样使用的：第一个参数指定后面可变参数的个数。 [/quote]  第一个参数确实是个数啊，但是个数是在运行时确定的

user: user-2
content: 就结贴了。。 有一种特殊情况。。如果你知道n的上限，而且这个上限不是很大时，可以这样，比如n上限是9 my_sum( n,     n>0?arr[0]:0,     n>1?arr[1]:0,     n>2?arr[2]:0,      n>3?arr[3]:0,     n>4?arr[4]:0,     n>5?arr[5]:0,     n>6?arr[6]:0,     n>7?arr[7]:0,     n>8?arr[8]:0 );

user: user-2
content: 引用 15 楼 super_miker 的回复:[quote=引用 14 楼 vnvlyp 的回复:] [quote=引用 13 楼 super_miker 的回复:]那C语言没有像lisp里面的apply类似的函数吗？ 有没有类似apply的函数：目测没有 能不能实现类似apply的功能：可以，但我觉得不可能做到跨平台，如果要跨平台只能是针对每个平台写一个版本，然后编译的时候根据平台链接对应版本[/quote] 能绕开汇编吗？[/quote] 应该不行，特别是64位的可以说不可能不用汇编，你这个需求我觉得最好的办法就是想别的方法。。比如要求你要调用函数的编写者提供更灵活的接口什么的 实在要这些用的话比较好的办法是用汇编写个类似apply的函数，做成一个库文件，然后在c里调用，链接的时候加上这个库文件就好了，如果你只要支持x86和x86_64架构的我觉得这应该还是可行的吧

user: user-0
content: 引用 14 楼 vnvlyp 的回复:[quote=引用 13 楼 super_miker 的回复:]那C语言没有像lisp里面的apply类似的函数吗？ 有没有类似apply的函数：目测没有 能不能实现类似apply的功能：可以，但我觉得不可能做到跨平台，如果要跨平台只能是针对每个平台写一个版本，然后编译的时候根据平台链接对应版本[/quote] 能绕开汇编吗？

user: user-2
content: 引用 13 楼 super_miker 的回复:那C语言没有像lisp里面的apply类似的函数吗？ 有没有类似apply的函数：目测没有 能不能实现类似apply的功能：可以，但我觉得不可能做到跨平台，如果要跨平台只能是针对每个平台写一个版本，然后编译的时候根据平台链接对应版本

user: user-0
content: 引用 10 楼 vnvlyp 的回复:如果要符合C99标准，能够跨平台的话，目测无解。。因为要调用那个函数，你必须把n和数组里所有int都存到寄存器或栈上(具体是寄存器还是栈和平台有关)，但是这个只能在运行的时候才可以做到，编译的时候因为不知道n，所以不可能实现这个。  如果你要求没那么严，只针对具体一个平台的话，那还是有很多办法的，比如用嵌入汇编，以下这个例子在符合System V x86_64标准的平台上应该可以满足你的要求，具体的话我用的64位Linux和gcc进行测试没有问题(暂时没有发现问题。。)  /* 	用以下命令编译，-g -Wall -O2不是必须的 	gcc main.c -o main -masm=intel -g -Wall -O2 */  #include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <time.h>  int get_sum( int n, ... ) { 	int sum, i; 	va_list va;  	va_start( va, n ); 	sum = 0; 	while ( n-- ) { 		i = va_arg( va, int ); 		sum += i; 	}  	return sum; }  int main( int argc, char *argv[] ) { 	int *arr; 	int sum, n, i;  	srand( time( NULL ) ); 	 	n = rand() % 100; 	printf( "n=%d\n", n ); 	arr = (int *)malloc( n * sizeof(int) );  	for ( i = 0; i < n; i++ ) { 		arr[i] = rand() % 1000; 	} 	  	sum = 0; 	for ( i = 0; i < n; i++ ) { 		sum += arr[i]; 	}  	printf( "sum=%d\n\n", sum );  	sum = 0; 	__asm__ __volatile__( 		"mov r15, 0\n\t" 		"mov r12, rax\n\t" 		 		"mov eax, edi\n\t" 		"test eax, eax\n\t" 		"jz .call\n\t"  		"mov esi, [r12]\n\t" 		"sub eax, 1\n\t" 		"jz .call\n\t"  		"mov edx, [r12+4]\n\t" 		"sub eax, 1\n\t" 		"jz .call\n\t"  		"mov ecx, [r12+8]\n\t" 		"sub eax, 1\n\t" 		"jz .call\n\t"  		"mov r8d, [r12+12]\n\t" 		"sub eax, 1\n\t" 		"jz .call\n\t"  		"mov r9d, [r12+16]\n\t" 		"sub eax, 1\n\t" 		"jz .call\n\t"  		".break:\n\t" 		"cdqe\n\t" 		"lea r15, [rax*8]\n\t" 		"sub rsp, r15\n\t"  		"mov r13, 0\n\t" 		"add r12, 16\n\t"  		".loop:\n\t" 		"add r12, 4\n\t" 		"mov r14d, [r12]\n\t" 		"mov [rsp+r13], r14d\n\t" 		"add r13, 8\n\t" 		"sub eax, 1\n\t" 		"jnz .loop\n\t"  		".call:\n\t" 		"mov eax, 0\n\t" 		"call rbx\n\t" 		"add rsp, r15\n\t" 		"mov %0, eax\n\t" 		: "=m"(sum) 		: "a"(arr), "D"(n), "b"(get_sum) 		: "rcx", "rdx", "rsi", "r8", "r9", "r12", "r13", "r14", "r15" 	); 	  	printf( "sum=%d\n", sum );  	free( arr );  	return 0; }   那C语言没有像lisp里面的apply类似的函数吗？

user: user-3
content: 我怎么感觉函数指针好呢。

user: user-2
content: 样例输出：(因为是随机生成数，所有结果不同) 第一个sum是用来测试结果是否正确的 第二个sum才是我这种方法得到的结果 [user ~/Documents/c/temp]# ./main  n=28 sum=12288  sum=12288 [user ~/Documents/c/temp]# ./main  n=2 sum=1143  sum=1143 [user ~/Documents/c/temp]# ./main  n=69 sum=34237  sum=34237   刚发现代码有一点点小问题，如果你觉得可行我再改改

user: user-2
content: 如果要符合C99标准，能够跨平台的话，目测无解。。因为要调用那个函数，你必须把n和数组里所有int都存到寄存器或栈上(具体是寄存器还是栈和平台有关)，但是这个只能在运行的时候才可以做到，编译的时候因为不知道n，所以不可能实现这个。  如果你要求没那么严，只针对具体一个平台的话，那还是有很多办法的，比如用嵌入汇编，以下这个例子在符合System V x86_64标准的平台上应该可以满足你的要求，具体的话我用的64位Linux和gcc进行测试没有问题(暂时没有发现问题。。)  /* 	用以下命令编译，-g -Wall -O2不是必须的 	gcc main.c -o main -masm=intel -g -Wall -O2 */  #include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <time.h>  int get_sum( int n, ... ) { 	int sum, i; 	va_list va;  	va_start( va, n ); 	sum = 0; 	while ( n-- ) { 		i = va_arg( va, int ); 		sum += i; 	}  	return sum; }  int main( int argc, char *argv[] ) { 	int *arr; 	int sum, n, i;  	srand( time( NULL ) ); 	 	n = rand() % 100; 	printf( "n=%d\n", n ); 	arr = (int *)malloc( n * sizeof(int) );  	for ( i = 0; i < n; i++ ) { 		arr[i] = rand() % 1000; 	} 	  	sum = 0; 	for ( i = 0; i < n; i++ ) { 		sum += arr[i]; 	}  	printf( "sum=%d\n\n", sum );  	sum = 0; 	__asm__ __volatile__( 		"mov r15, 0\n\t" 		"mov r12, rax\n\t" 		 		"mov eax, edi\n\t" 		"test eax, eax\n\t" 		"jz .call\n\t"  		"mov esi, [r12]\n\t" 		"sub eax, 1\n\t" 		"jz .call\n\t"  		"mov edx, [r12+4]\n\t" 		"sub eax, 1\n\t" 		"jz .call\n\t"  		"mov ecx, [r12+8]\n\t" 		"sub eax, 1\n\t" 		"jz .call\n\t"  		"mov r8d, [r12+12]\n\t" 		"sub eax, 1\n\t" 		"jz .call\n\t"  		"mov r9d, [r12+16]\n\t" 		"sub eax, 1\n\t" 		"jz .call\n\t"  		".break:\n\t" 		"cdqe\n\t" 		"lea r15, [rax*8]\n\t" 		"sub rsp, r15\n\t"  		"mov r13, 0\n\t" 		"add r12, 16\n\t"  		".loop:\n\t" 		"add r12, 4\n\t" 		"mov r14d, [r12]\n\t" 		"mov [rsp+r13], r14d\n\t" 		"add r13, 8\n\t" 		"sub eax, 1\n\t" 		"jnz .loop\n\t"  		".call:\n\t" 		"mov eax, 0\n\t" 		"call rbx\n\t" 		"add rsp, r15\n\t" 		"mov %0, eax\n\t" 		: "=m"(sum) 		: "a"(arr), "D"(n), "b"(get_sum) 		: "rcx", "rdx", "rsi", "r8", "r9", "r12", "r13", "r14", "r15" 	); 	  	printf( "sum=%d\n", sum );  	free( arr );  	return 0; }

user: user-4
content: //enter n array = (int *) malloc(sizeof(int) * n); // enter array int temp = 0; for(int i = 0; i < n; i++) { temp = my_sum(2, temp, array[i]); }

user: user-1
content: 引用 2 楼 super_miker 的回复:[quote=引用 1 楼 zhangxiangDavaid 的回复:] my_sum这种写法叫可变参数函数：http://blog.csdn.net/zhangxiangdavaid/article/details/38278249 依据my_sum的参数类型，你是不可能把array，传递过去的，不过可以这样调用：  int my_sum(int n, ...) { 	int res = 0; 	va_list va; 	va_start(va, n); 	do { 		res += va_arg(va, int); 	} while (--n); 	va_end(va); 	return res; } int main(void) { 	printf("%d\n", my_sum(2, 1, 2)); 	printf("%d\n", my_sum(3, 1, 2, 3)); 	printf("%d\n", my_sum(4, 1, 2, 3, 4));  	return 0; } //3 //6 //10   问题是n只能在运行时确定，而且数值范围未知。。。[/quote] 在C语言中，可变参数函数是这样使用的：第一个参数指定后面可变参数的个数。

user: user-0
content: 引用 1 楼 zhangxiangDavaid 的回复:my_sum这种写法叫可变参数函数：http://blog.csdn.net/zhangxiangdavaid/article/details/38278249 依据my_sum的参数类型，你是不可能把array，传递过去的，不过可以这样调用：  int my_sum(int n, ...) { 	int res = 0; 	va_list va; 	va_start(va, n); 	do { 		res += va_arg(va, int); 	} while (--n); 	va_end(va); 	return res; } int main(void) { 	printf("%d\n", my_sum(2, 1, 2)); 	printf("%d\n", my_sum(3, 1, 2, 3)); 	printf("%d\n", my_sum(4, 1, 2, 3, 4));  	return 0; } //3 //6 //10   问题是n只能在运行时确定，而且数值范围未知。。。

user: user-1
content: my_sum这种写法叫可变参数函数：http://blog.csdn.net/zhangxiangdavaid/article/details/38278249 依据my_sum的参数类型，你是不可能把array，传递过去的，不过可以这样调用：  int my_sum(int n, ...) { 	int res = 0; 	va_list va; 	va_start(va, n); 	do { 		res += va_arg(va, int); 	} while (--n); 	va_end(va); 	return res; } int main(void) { 	printf("%d\n", my_sum(2, 1, 2)); 	printf("%d\n", my_sum(3, 1, 2, 3)); 	printf("%d\n", my_sum(4, 1, 2, 3, 4));  	return 0; } //3 //6 //10