天天看點

linux怎麼寫一個函數,實作一個簡單的不定參數函數

一、基礎研究

寫一個函數showshr(char *,...)它可以接收不定數量的char *型參數,并列印這些指針所指向的字元串。這個題目也是要實作不定長參數的函數,而我們之前研究過printf()函數的列印機制,可以發現他們的原理是一樣的,隻不過printf()函數是點對點列印,即通過說明符識别要列印的資料類型和要列印的資料個數,它的參數就是要列印的資料本身,而這裡要求的函數沒有說明符,它的參數是要列印的字元串的位址,隻是在最後的參數為0以識别停止列印并傳回。

那麼我覺得這裡有兩種思路:一種是在showstr()函數内部使用輸出函數函數,這樣就要求我們将參數即要列印的字元串的位址轉換成字元串的值,即轉換成一個字元數組,這需要我們把所有參數指向的空間當作是一段空間,并将它的大小即總的字元串長度計算出來,這樣才能定義字元串數組并列印。還有一種思路是直接将字元串列印到螢幕上的固定位置,即将字元串指派到以b800為段位址的某個位址空間,這是更底層的寫法。但是我希望我在運作程式時能夠将将字元串列印到輸入指令的下一行,即列印位置是不固定的,是以我傾向于使用第一種思路。

那麼接下來可以開始寫程式了,首先我們把showstr的第一個形參命名為p,首先p的值是第一個字元串的首位址,判斷p是否為0,如果是則傳回函數,如果不是則輸出p指向的字元串,在這裡我們用putchar()函數輸出,因為每次隻能輸出一個字元,是以要循環輸出。那麼怎麼判斷字元串結束呢?我的辦法是判斷目前位置是否為符号,即是否為句号或感歎号,但這樣做的缺點是如果字元串不以符号結尾或者是中間出現符号的話輸出就會出現錯誤。

現在要跳到下一個參數來進行輸出,怎麼使p的值為下一個參數呢?我們知道形式參數是在棧裡存放的,而且是緊鄰的,是以如果傳遞的是p1、p2、p3,那麼入棧順序是p1、p2、

P3,因為他們的類型是char *型,是以p1的位址減2個位元組就是p2的位址,是以我們對p取址再減2就是下一個參數的位址。

編寫程式如下:

linux怎麼寫一個函數,實作一個簡單的不定參數函數

因為發現程式停不下來,是以我把while循環換成了for循環列印有限個結果。這個程式的運作結果如下:

linux怎麼寫一個函數,實作一個簡單的不定參數函數

可以發現,程式存在的問題有兩個:

(1)不能調到第三條字元串,導緻程式運作停不下來;

(2)列印的句号和問号有兩個。

對于第二個問題,是因為判斷語句裡面多了一條輸出語句。

在字元串的跳轉語句前面加一條輸出語句:

linux怎麼寫一個函數,實作一個簡單的不定參數函數

發現p隻有第一次改變了:

linux怎麼寫一個函數,實作一個簡單的不定參數函數

這是因為p是在棧段中的存儲第一個參數的首位址,它的位址是不變的,是以po=&p+1;是不變的,是以第一次改變後,p的值就不變了。那麼把p的位址給po,讓po每次加1來跳到下一個參數的首位址,再将*po賦給p,即将下一個參數所指向的字元串的首位址賦給p,這樣p就指向下一個字元串。

修改後的程式如下:

linux怎麼寫一個函數,實作一個簡單的不定參數函數

這裡要注意的是po是存儲參數的位址,而p是存儲字元串的首位址,是以po應該是int *型。運作結果為:

linux怎麼寫一個函數,實作一個簡單的不定參數函數

但是我覺得隻判斷最後的符号來判斷字元串是否結束不是很嚴謹,還有别的辦法判斷字元串是否結束嗎?查找資料可以發現字元串是以’\0’結尾的,是以我們應該可以判斷*(p+i)是否為‘\0’。修改後的程式如下:

linux怎麼寫一個函數,實作一個簡單的不定參數函數

二、擴充研究

1、我們之前是使用bp寄存器對棧進行操作來實作printf()函數,那麼如果用這種方法該怎麼實作這個題目?

答:我們可以用bp寄存器對棧操作來代替po指針的功能跳轉參數位址和字元串首位址。

修改後的程式如下:

linux怎麼寫一個函數,實作一個簡單的不定參數函數

這裡_BP還要加4是因為定義了兩個局部變量i和j,它們是存儲在棧中的,占4個位元組。

2、如果不用printf函數輸出可以嗎?

答:我們常用的輸出函數還有puts函數、putchar()函數,但是他們都需要頭檔案。我們也可以将結果輸出到螢幕上指定位置,即将每個字元串都輸出到b800段顯示。

三、研究總結

我們認識的輸出函數,都是将資料放進輸出流中,從底層看就是将資料放進一個緩存,之後再放到b800資料段來顯示,隻不過我們寫的底層輸出函數隻能将資料顯示在螢幕的固定位置,而我們使用的輸出函數會進行一些處理,使資料顯示在螢幕上合适的位置而已。

我們寫的這一��輸出函數隻能輸出字元串,而且無法控制輸出的位數等,而printf函數就引入了說明符,這樣就可以人為地控制資料輸出的格式等,更加的友善。

字元串其實就是字元數組,隻不過因為它是連續的,為了更友善地輸出,輸出函數為它提供了專門的輸出模式,這個模式也是以字元串的輸出為基礎的。

linux怎麼寫一個函數,實作一個簡單的不定參數函數