windows的CALLBACK函式修飾符

2021-08-20 16:39:00 字數 1331 閱讀 1437

參考:

對棧的操作是彙編層面做的,c語言並沒有對應的語句能夠直接操作棧,

c語言的標準庫

#include 中有幾個函式可以從棧中取數,但是並不能釋放(pop)棧

typedef char* va_list;

void va_start ( va_list ap, prev_param ); /* ansi version */

type va_arg ( va_list ap, type );

void va_end ( va_list ap );

看乙個例子

void fun(void)

void fun_2(int cnt)

fun為呼叫(主調)函式,get_val、debug_print為被調函式,實參push入棧,pop出棧相關的彙編**都是由編譯器自動生成的,這裡還有乙個細節問題,對於實參的入棧操作:實參只有呼叫者例如fun()和fun_2()知曉,顯然是實參的push操作被編譯到了呼叫函式中,至於出棧操作,就得分兩種情況了

(1)被調函式的形參型別和數目是固定的,從本質上看,入棧的實參內容的位元組數是固定的;

(2)被調函式是引數可變的,包括型別可變、數目可變。

對於(1),因為入棧的位元組數是固定的,所以出棧的位元組數也就固定了,因此呼叫函式和被調函式都可以完成出棧操作,那麼編譯器會把出棧指令編譯進呼叫函式、還是被調函式呢?答案是:跟編譯器有關,只要方法統一就行。vc編譯器預設的操作是把出棧編進主調函式(__cdecl ),有的編譯器的預設操作是把出棧編進被調函式(__stdcall)。

對於(2),入棧的位元組數只有呼叫者知道(注意這裡的語義,有人可能會說,例如通過printf的第乙個引數%xx,被調函式printf也可以知道實參的數目和型別,這種理解方式顯然是錯誤的,混淆了編譯期間與執行期間的概念,編譯器是不可能在編譯時判斷函式的實參內容的),對於不同的呼叫者,例如語句2和語句3,debug_print無論出棧多少位元組都是不合適的,因為它無法同時滿足所有呼叫者,所以,出棧的彙編**只能且必須編譯在主調函式中(__cdecl )。

__stdcall和 __cdecl 函式修飾符的區別就好理解了:__stdcall修飾的函式,其實參的出棧操作位於被調函式;__cdecl 修飾的函式,其出棧操作位於主調函式(這是vc的預設編譯方式)。

在windef.h中有這個巨集#define callback  __stdcall,這就明確了callback就是__stdcall

參考後話:對於被調函式清棧這種情況,只是說的把實參佔據的棧空間清掉,如果rn暫存器不足以容納返回值,被調函式還會把返回值入棧(或者保留一部分實參棧,把這個保留空間上的內容修改為返回值),以供主調函式使用

callback原始碼分析 callbacks

uvm的callback必須是提供者有預見性的留一些方法在function前後,這樣在使用的時候,進行遍歷排程即可 設計者,需要從uvm callback定義乙個基類,只定義function原型,定義乙個uvm callbacks,即pool型別 在物件類中使用register cb巨集來註冊cal...

jQuery原始碼分析系列 Callback深入

關於callbacks callbacks 的內部提供了jquery的 ajax 和 deferred 基本功能元件 在針對ajax處理中,用的最多的就是once memory的組合 所有的 佇列,不管任何時候增加的 保證只觸發一次 type completedeferred jquery.call...

Windows7 過渡 Windows10 的修改

對於新手和不大熟悉系統的朋友,可以使用it之家的 軟媒魔方 設定windows10,大部分設定問題都可以解決 以下介紹的都是在win10中令人頭疼的修改處理方法 不同點 一 win e 個人經驗 在win10的改動中,對win e快捷鍵改為了快速訪問 個人作為使用頻度最高,更傾向於開啟我的電腦 不同...