不定引數函式牽扯出來的棧的生長方向和大端小端模式

2021-07-29 03:57:06 字數 1896 閱讀 7110

主題:cpu的架構決定了大端小端模式和棧的生長方向。

前天參加深信服的專場招聘,問到不定引數函式的實現,當時只記得引數入參是從右到左,但是在棧中的存放位址大小當時就想不起來了,現在專門好好整理一下。 

首先引數從右到左壓棧的方式,這是c語言決定的,比如說pascal就是從左到右壓棧,所以pascal不支援不定引數函式。比如:

printf("%s%d%d\n", s, a, b);
格式字串是確定存在的,後面的變數都是不確定的或者說不知道有多少個。如果格式字串最後乙個入棧,位於棧頂,第乙個出棧然後解析格式字串得到不定參的個數,挨個出棧,這樣就很方便。pascal語言不支援可變長引數,而c語言支援這種特色,正是這個原因使得c語言函式引數入棧順序為從右至左。c方式引數入棧順序(從右至左)的好處就是可以動態變化引數個數。通過棧分析可知,自左向右的入棧方式,最前面的引數被壓在棧底。除非知道引數個數,否則是無法通過棧指標的相對位移求得最左邊的引數。這樣就變成了左邊引數的個數不確定,正好和動態引數個數的方向相反。 

這裡其實還涉及到c語言中呼叫約定所採用的方式: 

這裡第乙個得到格式字串的位址之後,後面的不定引數的位址是比這個大還是小了?這就是棧的生長方式決定的,51的棧是向高位址增長,intel的8031、8032、8048、8051系列使用向高位址增長的棧。但同樣是intel,在x86系列中全部使用向低位址增長的棧。其他公司的cpu中除arm的結構提供向高位址增長的棧選項外,多數都是使用向低位址增長的棧。順便提一下,x86使用的向高位址增長的堆,符合我們的使用習慣。 

也就是說x86中,棧底是高位址,棧頂是低位址,先入棧到高位址的棧底,然後到低位址的棧頂。所以不定引數的位址比格式字串的位址大。這樣設計可以使得堆和棧能夠充分利用空閒的位址空間。如果棧向**的話,我們就必須得指定棧和堆的乙個嚴格分界線,但這個分界線怎麼確定呢?平均分?但是有的程式使用的堆空間比較多,而有的程式使用的棧空間比較多。所以就可能出現這種情況:乙個程式因為棧溢位而崩潰的時候,其實它還有大量閒置的堆空間呢,但是我們卻無法使用這些閒置的堆空間。所以呢,最好的辦法就是讓堆和棧乙個向**,乙個向下漲,這樣它們就可以最大程度地共用這塊剩餘的位址空間,達到利用率的最大化!

所謂的大端模式,是指資料的低位儲存在記憶體的高位址中,而資料的高位,儲存在記憶體的低位址中;

所謂的小端模式,是指資料的低位儲存在記憶體的低位址中,而資料的高位儲存在記憶體的高位址中。

所以資料之間的位址大小看棧的生長方式,資料內的位址大小看大小端模式。在計算機系統中,我們是以位元組為單位的,每個位址單元都對應著乙個位元組,乙個位元組為8bit。但是在c語言中除了8bit的char之外,還有16bit的short型,32bit的long型(要看具體的編譯器),另外,對於位數大於8位的處理器,例如16位或者32位的處理器,由於暫存器寬度大於乙個位元組,那麼必然存在著乙個如果將多個位元組安排的問題。因此就導致了大端儲存模式和小端儲存模式。 

這裡引出主機位元組序和網路位元組序,主機位元組序是由cpu決定的,也就是大小端。我們常用的x86結構是小端模式。網路位元組序是固定的,就是大端模式,網路位元組序這是tcp/ip協議中定義好的一種資料格式,它是與你的機器的cpu,作業系統什麼的無關的,這樣可以保證資料在網路中傳輸時,不管怎麼樣都能正確的解釋!所以就有了網路位元組序到本機位元組序和本機位元組序到網路位元組序的轉換: 

htons:把unsigned short型別從主機序轉換到網路序 

htonl:把unsigned long型別從主機序轉換到網路序 

ntohs:把unsigned short型別從網路序轉換到主機序 

ntohl:把unsigned long型別從網路序轉換到主機序 

反正網路位元組序是固定的,這樣只要兩邊主機遵循大端模式傳送出去,以大端模式來接收,就不會有問題。

不定引數函式牽扯出來的棧的生長方向和大端小端模式

主題 cpu的架構決定了大端小端模式和棧的生長方向。首先引數從右到左壓棧的方式,這是c語言決定的,比如說pascal就是從左到右壓棧,所以pascal不支援不定引數函式。比如 printf s d d n s,a,b 格式字串是確定存在的,後面的變數都是不確定的或者說不知道有多少個。如果格式字串最後...

兩端對其牽扯出來的css

overflow wrap normal break word normal 表示在正常的單詞結束處換行。break word 表示如果行內沒有多餘的地方容納該單詞到結尾,則那些正常的不能被被分割的單詞會被強制分割換行。作用 用來說明當乙個字串太長,為防止其溢位,瀏覽器是否允許這樣的單詞中斷換行。w...

2020 11 28(不定引數的函式)

c c 將不定長引數的函式定義為 a.至少要有乙個引數 b.所有不定長的引數型別傳入時都是dword型別 c.需在某乙個引數中描述引數的總個數或將最後乙個引數賦值為結尾標記。有了這三個特性,就可以是實現不定引數的函式。printf函式就是利用第乙個引數來獲取引數總個數的,只需要檢查printf函式中...