In section 4.7.2 of deep anatomy of C language, an example of using function pointers is provided ~~~
Code and truth exist ~~~
#include <stdio.h>#include <string.h>char * fun(char *p1,char *p2){ int i=0; i=strcmp(p1,p2); if(i==0) { return p1; } else return p2;}int main(){ char *(*pf)(char * ,char *); pf=fun; printf("%s\n", (*pf)("aa","bb")); return 0;}
Output result: bb
Then the book says, "In the pF = fun; statement, fun and & fun are the same, because the function name is compiled into an address (vc6 )".
That is to say, if fun can be regarded as a variable, I mean, if it is, the memory address "& fun" stores this address value ~~~
The following is the result of compilation and display under GCC:
#include <stdio.h>#include <string.h>char * fun(char *p1,char *p2){ int i=0; i=strcmp(p1,p2); if(i==0) { return p1; } else { return p2; }}int main(){ char *(*pf)(char * ,char *); pf=fun; printf("%s\n", (*pf)("aa","bb")); printf("pf:%x ,&pf: %x ,*pf:%x fun:%x &fun:%x *fun:%x \n", pf,&pf,*pf,fun,&fun,*fun); return 0;}
Result:
Bb
PF: 400584, & PF: e4b8edb8, * PF: 400584 fun: 400584 & fun: 400584 * Fun: 400584
It (GCC) turned * Fun into a variable by compiling and running it. What did it do ~~~
Of course, the above results show that my previous analysis is consistent, but is the truth True ~~~
It may not be that simple ~~~
Because this is not the case in vs2008 ~~~
The disassembly code of the main function in:
int main(){004135A0 push ebp 004135A1 mov ebp,esp004135A3 sub esp,0CCh004135A9 push ebx 004135AA push esi 004135AB push edi 004135AC lea edi,[ebp-0CCh]004135B2 mov ecx,33h004135B7 mov eax,0CCCCCCCCh004135BC rep stos dword ptr es:[edi] char *(*pf)(char *p1,char *p2); pf=&fun;004135BE mov dword ptr [pf],offset @ILT+295(_fun) (41112Ch) printf("%s\n",(*pf)("aa","bb"));004135C5 mov esi,esp004135C7 push offset string "bb" (415744h)004135CC push offset string "aa" (41573Ch)004135D1 call dword ptr [pf]004135D4 add esp,8004135D7 cmp esi,esp004135D9 call @ILT+320(__RTC_CheckEsp) (411145h)004135DE mov esi,esp004135E0 push eax 004135E1 push offset string "%s\n" (415740h)004135E6 call dword ptr [__imp__printf (4182C4h)]004135EC add esp,8004135EF cmp esi,esp004135F1 call @ILT+320(__RTC_CheckEsp) (411145h) printf("pf:%x,&pf:%x,*pf:%x,fun:%x,&fun:%x,*fun%x,\n",pf,&pf,*pf,fun,&fun,*fun);004135F6 mov esi,esp004135F8 push offset @ILT+295(_fun) (41112Ch)004135FD push offset @ILT+295(_fun) (41112Ch)00413602 push offset @ILT+295(_fun) (41112Ch)00413607 mov eax,dword ptr [pf]0041360A push eax 0041360B lea ecx,[pf]0041360E push ecx 0041360F mov edx,dword ptr [pf]00413612 push edx 00413613 push offset string "pf:%x,&pf:%x,*pf:%x,fun:%x,&fun:"... (415A00h)00413618 call dword ptr [__imp__printf (4182C4h)]0041361E add esp,1Ch00413621 cmp esi,esp00413623 call @ILT+320(__RTC_CheckEsp) (411145h) getchar();00413628 mov esi,esp0041362A call dword ptr [MSVCR90D_NULL_THUNK_DATA (4182C0h)]00413630 cmp esi,esp00413632 call @ILT+320(__RTC_CheckEsp) (411145h) return 0;00413637 xor eax,eax}00413639 push edx 0041363A mov ecx,ebp0041363C push eax 0041363D lea edx,[ (413660h)]00413643 call @ILT+130(@_RTC_CheckStackVars@8) (411087h)00413648 pop eax 00413649 pop edx 0041364A pop edi 0041364B pop esi 0041364C pop ebx 0041364D add esp,0CCh00413653 cmp ebp,esp00413655 call @ILT+320(__RTC_CheckEsp) (411145h)0041365A mov esp,ebp0041365C pop ebp 0041365D ret 0041365E mov edi,edi00413660 db 01h 00413661 db 00h 00413662 db 00h 00413663 db 00h 00413664 db 68h 00413665 db 36h 00413666 db 41h 00413667 db 00h 00413668 db f8h 00413669 db ffh 0041366A db ffh 0041366B db ffh 0041366C db 04h 0041366D db 00h 0041366E db 00h 0041366F db 00h 00413670 db 74h 00413671 db 36h 00413672 db 41h 00413673 db 00h 00413674 db 70h 00413675 db 66h 00413676 db 00h
PS: the level of the Assembly has not been imported ~~~ Make a mark first ~~~
The result is as follows:
Note: The address output by vs monitor and print (the same as the print in GCC) is different. It is estimated that it is a bug. It is correct when printing the output, in addition, vs monitor does not regard * fun as a variable ~~~ However, it can still be output ~~~
So for vs monitor, fun is really a variable ~~~ It is char * (char *, char *), that is, the type of the function pointer ~~~
Note: I think some features of C language cannot be explained from the perspective of C language syntax, because C language is a relatively low-level language and is highly correlated with hardware (CPU and architecture, so if you need to understand it in depth, you still need to understand it from the perspective of lower-level compilation ~~~ Okay, find yourself a motivation to understand the assembly ~~~