C 05 goto模擬迴圈及函式的底層原理

2022-09-21 23:45:11 字數 3533 閱讀 3527

int n = 1;

int nsum = 0;

dowhile(n <= 100);

do_begin:

nsum = nsum + n;

n++;

if(n <= 100)

int n = 1;

int nsum = 0;

while(n <= 100)

while_begin:

if(n > 100)

nsum = nsum + n;

n++;

goto while_begin;

while_end:

for迴圈三個部分都有的情況
// for迴圈三個部分都有的情況

for(int n = 1, int nsum = 0; n <= 100; n++)

for_init:

int n = 1;

int nsum = 0;

goto for_cmp;

for_step:

n++;

for_cmp:

if(n > 100)

nsum = nsum + n;

goto for_step;

for_end:

for迴圈沒有初始化部分的情況
//	for迴圈沒有初始化部分的情況

int n = 1;

int nsum = 0;

for(; n <= 100; n++)

for_init:

goto for_cmp;

for_step:

n++;

for_cmp:

if(n > 100)

nsum = nsum + n;

goto for_step;

for_end:

for迴圈沒有初始化與步長部分的情況
//	for迴圈沒有初始化與步長部分的情況,下面這種情況就和while迴圈一樣

int n = 1;

int nsum = 0;

for(; n <= 100;)

for_cmp:

if(n > 100)

nsum = nsum + n;

n++;

goto for_cmp;

for_end:

for迴圈沒有判斷部分的情況
//	for迴圈沒有判斷部分的情況

for(int n = 1, int nsum = 0;; n++)

nsum = nsum + n;

}for_init:

int n = 1;

int nsum = 0;

goto for_striuct;

for_step:

n++;

for_striuct: //此處是迴圈體內的判斷

if(n > 100)

nsum = nsum + n;

goto for_step;

for_end:

wres(記憶體屬性):

任何作業系統(windows、liunx、安卓、ios等)上的程式在執行時,都有記憶體四大區,分別為:**區(code),資料區(data),棧區(stack),堆區(heap)

**區(code):存放二進位制可執行**,記憶體屬性為re

資料區(data):存放全域性變數,靜態變數和常量(c語言)

uninit:未初始化資料區:存放未初始化的全域性變數和靜態變數,記憶體屬性為rw

棧區(stack):先進後出,後進先出(類似彈夾),記憶體屬性為rw。經常被翻譯為堆疊,其實就是棧區,這是老一輩翻譯國外技術書籍時候的乙個習慣,喜歡成對成對的用詞,而中國傳統習慣是後者定性,例:禮無可恕,情有可原。那麼你就被放了,沒事。如果說 情有可原,禮無可恕,那麼你就攤上大事了。再例:牛奶,是奶;奶牛,是牛。所以指標陣列是陣列,陣列指標是指標

堆區(heap):記憶體屬性為rw

每個函式都有乙個屬於自己的棧空間,用來記錄函式的必要資訊

按呼叫約定傳參

__cdecl

__stdcall

__fastcall

解釋c呼叫約定,美國國標標準,預設呼叫約定

標準約定,微軟的規定,微軟作業系統使用的呼叫規定,windows api的標準呼叫約定

快速約定,只有微軟某一系列編譯器獨有的,未標準化,不同編譯器可能沒有或者實現不一致

引數傳遞方式

從右往左,通過棧傳遞

從右往左,通過棧傳遞

左數前兩個引數放在ecxedx暫存器中,其餘從右往左通過棧傳遞

誰清理棧上引數

呼叫者(caller)

被調者(callee)

被調者(callee)

編譯器引數

/gd

/gz

/gr

可變參支援

不支援不支援

在棧頂儲存返回位址

儲存呼叫方的棧資訊(呼叫方的棧底位置)

更新棧位置(在處理器裡)到被呼叫方的棧底處

在棧內開闢區域性變數的空間

​ 編譯器此時會統計區域性變數的大小(占多大空間),然後以此開闢足夠空間

​ 除錯版開闢的空間大於等於實際區域性變數的大小,發行版(優化版)開闢的空間小於等於實際區域性變數的大小

使用`/o1`和`/o2`編譯選項會根據變數使用情況,會分配小於等於變數大小的空間,例:
// 第一種優化情況

// 如果開了優化,編譯器不會給區域性變數nnum開闢空間

// 而是直接使用 printf("%d",3);

int nnum = 3;

printf("%d",nnum)

// 第二種優化情況

// 根據情況使用暫存器儲存變數

​ 編譯選項有/zi+/od(除錯版且不優化),則填充區域性變數空間為0xcc儲存暫存器環境

執行函式體

恢復暫存器環境

釋放區域性變數空間

恢復棧資訊到呼叫方

如果是__cdecl,先取出返回位址,並按此返回位址作流程更新,抵達新位址後,由呼叫方清理引數;

如果是__fastcall,__stdcall,先取出返回位址,並清理引數,然後按返回位址作流程更新

C語言05 函式及函式的呼叫過程

函式呼叫過程 集中處理非常樸素的道理,實踐以下 變參函式的話題。有意義機器碼 通過反彙編視窗確認 另外,也可以從列印函式名確認 void funtest void funvalarg char arg1,void myaddval int main int argc,char ar 作業系統為了好管...

C語言中goto 函式的使用場景

對於goto函式,我們應該不陌生,但是由於這個函式的跳轉難以約束,容易破壞程式的結構,所以一般不推薦使用,但又由它的強大的跳轉功能在一些場景中的應用十分優秀,所以這個函式有了很大的存在價值,下面來談一談它的使用場景 檢視以下例子 int main int argc,char ar loop exit...

Python迴圈語句及函式的定義

in 2 列表知識只是以後會講 比如 1,2,3,4,5,6,7 list one 1,2,3,4,5,6,7 forshuzi inlist one print shuzi print shuzi 100 print shuzi 1000 1 1011001 2102 1002 3103 1003...