日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

C语言可变参数只会用算啥本事?看我来抽丝剥茧干翻它!

發布時間:2023/12/2 编程问答 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C语言可变参数只会用算啥本事?看我来抽丝剥茧干翻它! 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

看山是山,看山不是山,最終看山才是山,并且是無窮的山巒。當我們學習一門技術的時候,起初是先模仿,但是最終是為了超越,也就是得到秘籍,看到本質。

于是,今天來繼續看可變參數,我們來分析這個過程,代碼如下:

聲明int add (int num,...);...會說明是個可變函數,這樣子編譯器在編譯遇到的函數的地方,就知道自動解析,依據傳入的參數,直接進行進棧,從而不需要報錯。

我們默認的函數,如果聲明是兩個參數,調用的是三個參數的話,最終會出錯,會提示你找不到實現體。

聲明完了后,實現函數,然后我們在使用的地方,直接傳入多個參數,就不會出問題。

我們這里要看下add里面的具體實現,第一個參數我們利用這個值,用來判定長度,循環的結束點。

然后使用va_start 來卡找到第一個參數的地址,我這節畫個圖,大家就能理解了。再一個你也就明白了,為什么是int add(int num,...);而不是int add(...); 因為如果是這個,你實現的時候,就沒法定位到起始地址,導致你無法解析后續的參數,這個明白了吧。

所以,編譯時候,系統會提示錯誤,規定...參數前面必須有一個有名參數,否則系統編譯的時候,你在實現體里面,無法做處理。這里就是?va_start(valist,num);

然后我們使用va_arg 去獲取后續的參數,第一個是起始地址,第二個是后面緊跟著的數據,該以哪個大小去解析。我們這里是int,都是這個尺寸,所以用了循環。

在printf里面,使用的是%s ,%f這類處理,依據這個會變化。

使用完成后,就可以用va_end來結束指針。

我們如果把調用地方改成add(5,a,b);最終能輸出出來結果,但是非常亂,原因很簡單,這里的第一個參數5,讓遍歷尋找了棧上面的一些臟數據,導致結果未知。

我們如果把int b=6改成float b=6;會發生什么神奇的現象呢?出現了神奇的結果,原因很簡單,float 進入棧的時候,占用的空間比int大,但是我們執行的時候,用了int大小去解析了這個數據,導致出現問題。

我們來看下如何修正這個問題,就需要格式化處理了,第一個參數,我們把它調整下,變成char *format,我們把代碼改成這個,

為什么這里有float變為了double,主要是方便系統進行處理,升級后你 解析的時候,就要用double去解析,否則的話你處理完數據,ap指針就沒有指到下一個位置,導致出錯。

不過這個問題現在你不需要擔心,如果你沒有寫對,系統會在編譯時候提醒你,直接系統報錯,讓你去修改的。

這樣子看下來,是不是覺得可變參數也沒多神奇了?簡單說下就是編譯器支持...讓函數參數可變,同時保留一個有名參數,讓實現體可以用這個去定位到起始位置,然后進行遍歷解析,完成邏輯處理。

我們把這個再抽象一層,簡單來說,就是一組數據約束,存放在一起,然后我們依據一個格式化參數,對這個數據進行解析處理。當你看到這個的時候,就突然明白,協議的概念。

協議就是約定,約定雙方同時遵循一個規則,同時遵守,就是協議。TCP/IP協議,ELF文件解析協議。

當你抽象到這里,基本上就大徹大悟,一切處理都是協議頭 數據( 校驗)。

在今天最后,我們來看下反編譯后的代碼,就明白了第一個參數的地址的意義,我這里用的int b=6;原因是如果是float的話,指令會比較復雜,不方便我們學習。

這里可以看到,我們地參數是 %d,%d??a b??這三個,在匯編代碼中,可以看到,

rbp-0x8 放的是b的值,6

rbp-0xc 放的是a的值,5

rbp-0x14,放著一個地址4007ec,這地方就是%d,%d 常量字串位置

所以我們add函數實現里面,fmt拿到的就是rbp-0x14的地址,也就是第一個參數,隨后的解析就是依據給的格式,把對應數據解析出來,移動指針ap的位置到合適地方(依據對齊原則,以及sizeof(數據類型)

聲明:

本文于網絡整理,版權歸原作者所有,如來源信息有誤或侵犯權益,請聯系我們刪除或授權事宜。

總結

以上是生活随笔為你收集整理的C语言可变参数只会用算啥本事?看我来抽丝剥茧干翻它!的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。