亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C > 正文

基于函數指針的示例分析

2020-02-24 14:30:23
字體:
來源:轉載
供稿:網友

本文為大家詳細介紹了關于基于函數指針的示例分析,相信很多小伙伴們都是不了解的,那么我們現在就跟隨武林小編一起去看看基于函數指針的示例分析的具體內容吧。

第一個:
------------------------------------------------------

?

#include <stdio.h>
#include <string.h>
void tell_me(int f(const char *, const char *));
int main(void)
{
?? tell_me(strcmp);
?? tell_me(main);
?? return 0;
}
void tell_me(int f(const char *, const char *))
{
?? if (f == strcmp) /* <-----我不理解這里*/
????? printf("Address of strcmp(): %p/n", f);
?? else
????? printf("Function address: %p/n", f);
}


--------------------------------------------------------------
其中我不理解的是,這個程序表達的應該是說f是一個指向函數的指針,判斷的時候是判斷f是否指向函數strcmp,如果是的話,就輸出strcmp這個函數的地址.如果不是,就輸出main函數的地址
因為函數名可以作為指針,所以if (f == strcmp)應該是說判斷2個指針的地址是否相同對吧?
我用gdb 斷點到此,print f和printfstrcmp得到的是不同的地址啊,并且可以發現f和*f的內容居然一樣,strcmp和*strcmp也一樣,請問是什么原因,如何解釋?

(gdb) print f
$1 = (int (*)(const char *, const char *)) 0x8048310 <strcmp@plt>
(gdb) print strcmp
$2 = {<text variable, no debug info>} 0xb7e59d20 <strcmp>
(gdb) n
16 printf("Address of strcmp(): %p/n", f);
(gdb) print strcmp
$3 = {<text variable, no debug info>} 0xb7e59d20 <strcmp>
(gdb) print *strcmp
$4 = {<text variable, no debug info>} 0xb7e59d20 <strcmp>
(gdb) print *f
$5 = {int (const char *, const char *)} 0x8048310 <strcmp@plt>
(gdb) n
Address of strcmp(): 0x8048310
19 }
(gdb) n
后來我查到plt是指的過程鏈接表,是不是說只有在執行到f == strcmp時候,才把f的地址和strcmp的位置指向同一位置?

?

后來別人通過反匯編發現的情況:
==============================================
如下紅色的幾行,main與strcmp此時為常量(你也會發現沒有.data段),在匯編代碼中他是把這兩個常量寫入函數堆棧,然后調用函數,作出對比,然后輸出。而你所說的 f ,也就是函數參數,實際上它只作為預分配的參考(匯編代碼中,你是找不到 f 的)。
-------------------------------------------------------------------------------------
.file "1.c"
.text
.globl main
.type main, @function
main:
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
pushl %ecx
subl $4, %esp
movl $strcmp, (%esp)
call tell_me
movl $main, %eax
movl %eax, (%esp)
call tell_me
movl $0, %eax
addl $4, %esp
popl %ecx
popl %ebp
leal -4(%ecx), %esp
ret
.size main, .-main
.section .rodata
.LC0:
.string "Address of strcmp(): %p/n"
.LC1:
.string "Function address: %p/n"
.text
.globl tell_me
.type tell_me, @function
tell_me:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
cmpl $strcmp, 8(%ebp)
jne .L4
movl 8(%ebp), %eax
movl %eax, 4(%esp)
movl $.LC0, (%esp)
call printf
jmp .L6
.L4:
movl 8(%ebp), %eax
movl %eax, 4(%esp)
movl $.LC1, (%esp)
call printf
.L6:
leave
ret
.size tell_me, .-tell_me
.ident "GCC: (Ubuntu 4.3.3-5ubuntu4) 4.3.3"
.section .note.GNU-stack,"",@progbits
==================================================
00401090 push ebp //第一題的反匯編
00401091 mov ebp,esp
00401093 sub esp,40h
00401096 push ebx
00401097 push esi
00401098 push edi
00401099 lea edi,[ebp-40h]
0040109C mov ecx,10h
004010A1 mov eax,0CCCCCCCCh //應該說在函數傳遞時,f與strcmp的地址都相同
004010A6 rep stos dword ptr [edi]
13: printf("%0x/t%0x/n",f,strcmp); //看這里,輸出f與strcmp的地址是相同的
004010A8 push offset strcmp (004011a0)
004010AD mov eax,dword ptr [ebp+8]
004010B0 push eax
004010B1 push offset string "%0x/t%0x/n" (0042201c)
004010B6 call printf (00401120)
004010BB add esp,0Ch
14: if (f == strcmp) /* <-----我不理解這里*/ //比較后,輸出的地址同樣是一樣的,
004010BE cmp dword ptr [ebp+8],offset strcmp (004011a0)
004010C5 jne tell_me+4Ah (004010da)
15: printf("Address of strcmp(): %0x/n", f);
004010C7 mov ecx,dword ptr [ebp+8]
004010CA push ecx
004010CB push offset string "Address of strcmp(): %0x/n" (00422044)
004010D0 call printf (00401120)
004010D5 add esp,8
16: else
004010D8 jmp tell_me+5Bh (004010eb)
17: printf("Function address: %p/n", f);
004010DA mov edx,dword ptr [ebp+8]
004010DD push edx
004010DE push offset string "Function address: %p/n" (00422028)
004010E3 call printf (00401120)
004010E8 add esp,8=======================================================

第二個:
--------------------------------------------------------------------------------------------

?

#include <stdio.h>
#include <string.h>
int main(void)
{
?? char p1[20] = "abc", *p2 = "pacific sea";
?? printf("%s %s %s/n", p1, p2, strcat(p1, p2)); /*<-----問題出在這里*/
?? return 0;
}


---------------------------------------------------------------------------------------------
輸出我的認為應該是先輸出p1, p2以后再執行strcat. 但是實際輸出的情況:
abcpacific sea pacific sea abcpacific sea
可以發現strcat先于p1執行,改變了p1的內容,請問這個內部是怎么的順序?難道printf不是順序執行的?
=======================================================

得到的解答:
不同的編譯器printf的函數參數進棧順序不同,printf函數中的strcat可以看反匯編代碼.
6: printf("%s/t%s/t%s/n", p1, p2, strcat(p1, p2)); /*<-----問題出在這里*/
00401045 mov edx,dword ptr [ebp-18h]
00401048 push edx
00401049 lea eax,[ebp-14h]
0040104C push eax
0040104D call strcat (00401130) //可以看到是先調用strcat函數的,
00401052 add esp,8
00401055 push eax
00401056 mov ecx,dword ptr [ebp-18h]
00401059 push ecx
0040105A lea edx,[ebp-14h]
0040105D push edx
0040105E push offset string "%s/t%s/t%s/n" (0042201c)
00401063 call printf (004010a0) //最后調用printf函數輸出
00401068 add esp,10h
===============================================
匯編直觀而簡單的說明了一些疑問....
再說下gcc如何產生匯編代碼:
1: gcc -S main.c 可以生成
2: gcc -c main.c 生成main.o
objdump -S -D main.o > main.asm
我更傾向于第二種.

本篇文章是對基于函數指針的示例分析,需要的朋友參考下,更多相關內容就在武林技術頻道。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲天堂精品在线| 91九色国产视频| 国产性猛交xxxx免费看久久| 成人春色激情网| 日韩一区二区久久久| 国产精品美女久久久久久免费| 国产精品久久77777| 久久精品视频导航| 久久99久久久久久久噜噜| 日本一区二区在线免费播放| 欧美日韩亚洲高清| 欧美一区视频在线| 一个人看的www欧美| 91亚洲精品视频| 日本欧美在线视频| 成人h片在线播放免费网站| 亚洲男子天堂网| 色青青草原桃花久久综合| 综合激情国产一区| 精品亚洲一区二区三区四区五区| 日本不卡免费高清视频| 久久精品在线视频| 91精品国产自产在线| 国产91对白在线播放| 两个人的视频www国产精品| 欧美日韩美女视频| 91久久精品一区| 亚洲一区二区中文字幕| 欧美精品在线看| 国产精品视频久久久| 亚洲综合在线做性| 国产精品视频xxx| 欧美日韩国产色视频| 羞羞色国产精品| 亚洲黄色免费三级| 国产一区二区在线免费视频| 成人www视频在线观看| 红桃视频成人在线观看| 91日韩在线播放| 欧美壮男野外gaytube| 欧美日韩一区二区免费在线观看| 日本在线观看天堂男亚洲| 人人爽久久涩噜噜噜网站| 国产精品久久久久aaaa九色| 久久香蕉频线观| 久久黄色av网站| 国产亚洲精品一区二555| 国产三级精品网站| 91sao在线观看国产| 欧美午夜精品久久久久久久| 91久久国产精品| 中文字幕久精品免费视频| 91中文字幕在线观看| 亚洲精品成a人在线观看| 久久免费高清视频| 91高清视频在线免费观看| 国产婷婷成人久久av免费高清| 欧美在线性爱视频| 国产成人精品视| 91精品啪aⅴ在线观看国产| 欧美激情一区二区三区久久久| 日韩视频精品在线| 亚洲精品国产精品自产a区红杏吧| 亚洲第一福利在线观看| 欧美一级片免费在线| 粉嫩老牛aⅴ一区二区三区| 高清视频欧美一级| 黄色91在线观看| 久久视频在线直播| 日韩69视频在线观看| 欧美日韩中文在线| 国产日韩欧美综合| 欧美乱妇高清无乱码| 日韩福利在线播放| 国产精品久久久久9999| 国产精品美女免费| 日韩免费中文字幕| 91性高湖久久久久久久久_久久99| 亚洲国产又黄又爽女人高潮的| 国产在线视频欧美| 日韩不卡在线观看| 欧美成人午夜激情| 日日狠狠久久偷偷四色综合免费| 亚洲午夜未满十八勿入免费观看全集| 亚洲欧洲日产国码av系列天堂| 伊人青青综合网站| 欧美国产日韩一区二区在线观看| 在线观看91久久久久久| 国产盗摄xxxx视频xxx69| 欧美日韩中文在线观看| 亚洲欧美日韩视频一区| 亚洲福利影片在线| 久久久免费观看视频| 欧美成人自拍视频| 粉嫩老牛aⅴ一区二区三区| 九九热精品视频| 中文字幕日韩欧美在线视频| 大胆欧美人体视频| 欧美日韩高清区| 久久久精品亚洲| 中文字幕精品一区二区精品| 亚洲精品美女久久久| 亚洲女人天堂视频| 久久精品成人欧美大片古装| 成人精品在线视频| 国产一区二区三区在线看| 欧美日本啪啪无遮挡网站| 国外成人在线视频| 国产综合久久久久久| 国产精品女人久久久久久| 成人久久一区二区三区| 欧美一区二区三区四区在线| 伊人一区二区三区久久精品| 亚洲va欧美va国产综合剧情| 在线成人一区二区| 欧美成人精品在线视频| 欧洲亚洲在线视频| 欧美裸体男粗大视频在线观看| 成人www视频在线观看| 国产精品美乳一区二区免费| 久久人人爽人人爽人人片av高清| 亚洲美女av在线播放| 欧美性猛交xxxx乱大交蜜桃| 亚洲精品久久久久| 日韩av免费在线播放| 亚洲精品国产品国语在线| 久久偷看各类女兵18女厕嘘嘘| 日韩中文字幕第一页| 国产精品91久久久久久| 日韩av免费网站| 国产成人精品电影久久久| 亚洲在线一区二区| 日韩欧中文字幕| 欧美日韩aaaa| 欧美精品在线免费观看| 欧美丰满老妇厨房牲生活| 欧洲亚洲在线视频| 动漫精品一区二区| 亚洲欧美日韩成人| 国产精品麻豆va在线播放| 日韩av观看网址| 国产精品一区二区三区在线播放| 亚洲欧洲激情在线| 欧美性xxxx极品hd欧美风情| 成人美女免费网站视频| 成人国产在线激情| 国产福利精品在线| 日韩禁在线播放| 亚洲天堂2020| 亚洲电影免费观看高清完整版在线| 国产精品久久久一区| 97香蕉久久夜色精品国产| 久热精品视频在线观看一区| 久久久久久亚洲| 亚洲自拍高清视频网站| 久久精品精品电影网| 国产自摸综合网| 欧美亚洲另类激情另类| 久久五月情影视| 亚洲自拍偷拍色图| 97色伦亚洲国产| 久久精品中文字幕一区| 在线精品国产欧美| 亚洲国产日韩精品在线|