user-0 提问: C语言函数指针问题

回复:
user: user-0
content: 引用 14 楼 jiandingzhe 的回复:[quote=引用 5 楼 szllong123 的回复:] [quote=引用 2 楼 user-7 的回复:] 函数参数为函数指针类型或函数类型时，传递的都是函数指针，应该无区别 int f(int(*alg)(int a,int b),int a,int b)  //参数1为函数指针类型 int f(int(alg)(int a,int b),int a,int b)   //参数1为函数类型 我是想问这两种在实际中有什么差别，是按照传值传地址什么说法么，怎么运行的？[/quote] 函数体传个啥值, 就是简便写法而已.  你如果要简化, 可以用typedef.  typedef int (*AlgorithmType) (int, int);  ... MyFunc(AlgorithmType op, ......) [/quote] 这个我知道，就是从这样改过来的！

user: user-1
content: 引用 5 楼 szllong123 的回复:[quote=引用 2 楼 user-7 的回复:] 函数参数为函数指针类型或函数类型时，传递的都是函数指针，应该无区别 int f(int(*alg)(int a,int b),int a,int b)  //参数1为函数指针类型 int f(int(alg)(int a,int b),int a,int b)   //参数1为函数类型 我是想问这两种在实际中有什么差别，是按照传值传地址什么说法么，怎么运行的？[/quote] 函数体传个啥值, 就是简便写法而已.  你如果要简化, 可以用typedef.  typedef int (*AlgorithmType) (int, int);  ... MyFunc(AlgorithmType op, ......)

user: user-0
content: 用gcc汇编之后是这样的，我gcc 版本 4.8.2 20131017 (Red Hat 4.8.2-1) (GCC)         .file   "main.cpp"         .text         .globl  _Z2f1PFiiiEii         .type   _Z2f1PFiiiEii, @function _Z2f1PFiiiEii: .LFB0:         .cfi_startproc         pushq   %rbp         .cfi_def_cfa_offset 16         .cfi_offset 6, -16         movq    %rsp, %rbp         .cfi_def_cfa_register 6         subq    $16, %rsp         movq    %rdi, -8(%rbp)         movl    %esi, -12(%rbp)         movl    %edx, -16(%rbp)         movl    -16(%rbp), %ecx         movl    -12(%rbp), %edx         movq    -8(%rbp), %rax         movl    %ecx, %esi         movl    %edx, %edi         call    *%rax         leave         .cfi_def_cfa 7, 8         ret         .cfi_endproc .LFE0:         .size   _Z2f1PFiiiEii, .-_Z2f1PFiiiEii         .globl  _Z2f2PFiiiEii         .type   _Z2f2PFiiiEii, @function _Z2f2PFiiiEii: .LFB1:         .cfi_startproc         pushq   %rbp         .cfi_def_cfa_offset 16         .cfi_offset 6, -16         movq    %rsp, %rbp         .cfi_def_cfa_register 6         subq    $16, %rsp         movq    %rdi, -8(%rbp)         movl    %esi, -12(%rbp)         movl    %edx, -16(%rbp)         movl    -16(%rbp), %ecx         movl    -12(%rbp), %edx         movq    -8(%rbp), %rax         movl    %ecx, %esi         movl    %edx, %edi         call    *%rax         leave         .cfi_def_cfa 7, 8         ret         .cfi_endproc .LFE1:         .size   _Z2f2PFiiiEii, .-_Z2f2PFiiiEii         .globl  _Z3addii         .type   _Z3addii, @function _Z3addii: .LFB2:         .cfi_startproc         pushq   %rbp         .cfi_def_cfa_offset 16         .cfi_offset 6, -16         movq    %rsp, %rbp         .cfi_def_cfa_register 6         movl    %edi, -4(%rbp)         movl    %esi, -8(%rbp)         movl    -8(%rbp), %eax         movl    -4(%rbp), %edx         addl    %edx, %eax         popq    %rbp         .cfi_def_cfa 7, 8         ret         .cfi_endproc .LFE2:         .size   _Z3addii, .-_Z3addii         .globl  _Z3subii         .type   _Z3subii, @function _Z3subii: .LFB3:         .cfi_startproc         pushq   %rbp         .cfi_def_cfa_offset 16         .cfi_offset 6, -16         movq    %rsp, %rbp         .cfi_def_cfa_register 6         movl    %edi, -4(%rbp)         movl    %esi, -8(%rbp)         movl    -8(%rbp), %eax         movl    -4(%rbp), %edx         subl    %eax, %edx         movl    %edx, %eax         popq    %rbp         .cfi_def_cfa 7, 8         ret         .cfi_endproc .LFE3:         .size   _Z3subii, .-_Z3subii         .section        .rodata .LC0:         .string " %d+%d=%d\n" .LC1:         .string " %d-%d=%d\n"         .text  .globl  main         .type   main, @function main: .LFB4:         .cfi_startproc         pushq   %rbp         .cfi_def_cfa_offset 16         .cfi_offset 6, -16         movq    %rsp, %rbp         .cfi_def_cfa_register 6         subq    $16, %rsp         movl    $1, -4(%rbp)         movl    $2, -8(%rbp)         movl    -8(%rbp), %edx         movl    -4(%rbp), %eax         movl    %eax, %esi         movl    $_Z3addii, %edi         call    _Z2f1PFiiiEii         movl    %eax, %ecx         movl    -8(%rbp), %edx         movl    -4(%rbp), %eax         movl    %eax, %esi         movl    $.LC0, %edi         movl    $0, %eax         call    printf         movl    -8(%rbp), %edx         movl    -4(%rbp), %eax         movl    %eax, %esi         movl    $_Z3subii, %edi         call    _Z2f2PFiiiEii         movl    %eax, %ecx         movl    -8(%rbp), %edx         movl    -4(%rbp), %eax         movl    %eax, %esi         movl    $.LC1, %edi         movl    $0, %eax         call    printf         movl    $0, %eax         leave         .cfi_def_cfa 7, 8         ret         .cfi_endproc .LFE4:         .size   main, .-main         .ident  "GCC: (GNU) 4.8.2 20131017 (Red Hat 4.8.2-1)"         .section        .note.GNU-stack,"",@progbits

user: user-0
content: 我觉得我得把源码再贴出来一边  #include <stdio.h>  int f1(int(*alg)(int a,int b),int a,int b) {         return alg(a,b); } int f2(int(alg)(int a,int b),int a,int b) {         return alg(a,b); } int add(int a,int b) {         return a+b; } int sub(int a,int b) {         return a-b; } int main() {         int a=1,b=2;         printf(" %d+%d=%d\n",a,b,f1(add,a,b));         printf(" %d-%d=%d\n",a,b,f2(sub,a,b));         return 0; }

user: user-0
content: _Z2f1PFiiiEii: .LFB0:         .cfi_startproc         pushq   %rbp         .cfi_def_cfa_offset 16         .cfi_offset 6, -16         movq    %rsp, %rbp         .cfi_def_cfa_register 6         subq    $16, %rsp         movq    %rdi, -8(%rbp)         movl    %esi, -12(%rbp)         movl    %edx, -16(%rbp)         movl    -16(%rbp), %ecx         movl    -12(%rbp), %edx         movq    -8(%rbp), %rax         movl    %ecx, %esi         movl    %edx, %edi         call    *%rax         leave         .cfi_def_cfa 7, 8         ret         .cfi_endproc .LFE0:         .size   _Z2f1PFiiiEii, .-_Z2f1PFiiiEii         .globl  _Z2f2PFiiiEii         .type   _Z2f2PFiiiEii, @function _Z2f2PFiiiEii: .LFB1:         .cfi_startproc         pushq   %rbp         .cfi_def_cfa_offset 16         .cfi_offset 6, -16         movq    %rsp, %rbp         .cfi_def_cfa_register 6         subq    $16, %rsp         movq    %rdi, -8(%rbp)         movl    %esi, -12(%rbp)         movl    %edx, -16(%rbp)         movl    -16(%rbp), %ecx         movl    -12(%rbp), %edx         movq    -8(%rbp), %rax         movl    %ecx, %esi         movl    %edx, %edi         call    *%rax         leave         .cfi_def_cfa 7, 8         ret         .cfi_endproc  我自己汇编了下是这样的

user: user-2
content: 就好比形参你用个数组，也会退化成指针。typedef吧，让代码清楚易读...

user: user-0
content: 引用 7 楼 u012503290 的回复:23:       printf(" %d+%d=%d\n",a,b,f(add,a,b)); 0040B8A6   mov         eax,dword ptr [ebp-8] 0040B8A9   push        eax 0040B8AA   mov         ecx,dword ptr [ebp-4] 0040B8AD   push        ecx 0040B8AE   push        offset @ILT+10(_add) (0040100f) 0040B8B3   call        @ILT+5(_f) (0040100a) 0040B8B8   add         esp,0Ch 0040B8BB   push        eax 0040B8BC   mov         edx,dword ptr [ebp-8] 0040B8BF   push        edx 0040B8C0   mov         eax,dword ptr [ebp-4] 0040B8C3   push        eax 0040B8C4   push        offset string " %d+%d=%d\n" (00420fa8) 0040B8C9   call        printf (00401090) 0040B8CE   add         esp,10h 25:       printf(" %d+%d=%d\n",a,b,ff(add,a,b)); 0040B8FC   mov         edx,dword ptr [ebp-8] 0040B8FF   push        edx 0040B900   mov         eax,dword ptr [ebp-4] 0040B903   push        eax 0040B904   push        offset @ILT+10(_add) (0040100f) 0040B909   call        @ILT+20(_ff) (00401019) 0040B90E   add         esp,0Ch 0040B911   push        eax 0040B912   mov         ecx,dword ptr [ebp-8] 0040B915   push        ecx 0040B916   mov         edx,dword ptr [ebp-4] 0040B919   push        edx 0040B91A   push        offset string " %d+%d=%d\n" (00420fa8) 0040B91F   call        printf (00401090) 0040B924   add         esp,10h 两种调用方法都一样，都是直接push函数指针。 你这个汇编有问题把，我在主函数中已经改成了两个都用的函数f

user: user-3
content: 引用 8 楼 szllong123 的回复:[quote=引用 7 楼 u012503290 的回复:] 23:       printf(" %d+%d=%d\n",a,b,f(add,a,b)); 0040B8A6   mov         eax,dword ptr [ebp-8] 0040B8A9   push        eax 0040B8AA   mov         ecx,dword ptr [ebp-4] 0040B8AD   push        ecx 0040B8AE   push        offset @ILT+10(_add) (0040100f) 0040B8B3   call        @ILT+5(_f) (0040100a) 0040B8B8   add         esp,0Ch 0040B8BB   push        eax 0040B8BC   mov         edx,dword ptr [ebp-8] 0040B8BF   push        edx 0040B8C0   mov         eax,dword ptr [ebp-4] 0040B8C3   push        eax 0040B8C4   push        offset string " %d+%d=%d\n" (00420fa8) 0040B8C9   call        printf (00401090) 0040B8CE   add         esp,10h 25:       printf(" %d+%d=%d\n",a,b,ff(add,a,b)); 0040B8FC   mov         edx,dword ptr [ebp-8] 0040B8FF   push        edx 0040B900   mov         eax,dword ptr [ebp-4] 0040B903   push        eax 0040B904   push        offset @ILT+10(_add) (0040100f) 0040B909   call        @ILT+20(_ff) (00401019) 0040B90E   add         esp,0Ch 0040B911   push        eax 0040B912   mov         ecx,dword ptr [ebp-8] 0040B915   push        ecx 0040B916   mov         edx,dword ptr [ebp-4] 0040B919   push        edx 0040B91A   push        offset string " %d+%d=%d\n" (00420fa8) 0040B91F   call        printf (00401090) 0040B924   add         esp,10h 两种调用方法都一样，都是直接push函数指针。 你这个汇编有问题把，我在主函数中已经改成了两个都用的函数f[/quote] 自己改了下： f(int(*alg)(int a,int b),int a,int b) ff(int(alg)(int a,int b),int a,int b) so~

user: user-3
content: 23:       printf(" %d+%d=%d\n",a,b,f(add,a,b)); 0040B8A6   mov         eax,dword ptr [ebp-8] 0040B8A9   push        eax 0040B8AA   mov         ecx,dword ptr [ebp-4] 0040B8AD   push        ecx 0040B8AE   push        offset @ILT+10(_add) (0040100f) 0040B8B3   call        @ILT+5(_f) (0040100a) 0040B8B8   add         esp,0Ch 0040B8BB   push        eax 0040B8BC   mov         edx,dword ptr [ebp-8] 0040B8BF   push        edx 0040B8C0   mov         eax,dword ptr [ebp-4] 0040B8C3   push        eax 0040B8C4   push        offset string " %d+%d=%d\n" (00420fa8) 0040B8C9   call        printf (00401090) 0040B8CE   add         esp,10h 25:       printf(" %d+%d=%d\n",a,b,ff(add,a,b)); 0040B8FC   mov         edx,dword ptr [ebp-8] 0040B8FF   push        edx 0040B900   mov         eax,dword ptr [ebp-4] 0040B903   push        eax 0040B904   push        offset @ILT+10(_add) (0040100f) 0040B909   call        @ILT+20(_ff) (00401019) 0040B90E   add         esp,0Ch 0040B911   push        eax 0040B912   mov         ecx,dword ptr [ebp-8] 0040B915   push        ecx 0040B916   mov         edx,dword ptr [ebp-4] 0040B919   push        edx 0040B91A   push        offset string " %d+%d=%d\n" (00420fa8) 0040B91F   call        printf (00401090) 0040B924   add         esp,10h 两种调用方法都一样，都是直接push函数指针。

user: user-4
content: 实际中编译的时候都是按函数指针来处理的，后者是“隐式”的

user: user-0
content: 引用 2 楼 user-7 的回复:函数参数为函数指针类型或函数类型时，传递的都是函数指针，应该无区别 int f(int(*alg)(int a,int b),int a,int b)  //参数1为函数指针类型 int f(int(alg)(int a,int b),int a,int b)   //参数1为函数类型 我是想问这两种在实际中有什么差别，是按照传值传地址什么说法么，怎么运行的？

user: user-5
content: 2楼，果断mark！

user: user-6
content: typedef

user: user-7
content: 函数参数为函数指针类型或函数类型时，传递的都是函数指针，应该无区别 int f(int(*alg)(int a,int b),int a,int b)  //参数1为函数指针类型 int f(int(alg)(int a,int b),int a,int b)   //参数1为函数类型

user: user-0
content: 搞错了，没注意到，这是从网上直接拷贝的，主函数应该是 void main() {//函数指针初步应用 	int a=1,b=2; 	printf(" %d+%d=%d\n",a,b,f(add,a,b)); 	printf(" %d-%d=%d\n",a,b,f(sub,a,b)); }