C語言中的宏 #define _INTSIZEOF(n) 與 可變參數函數

在學習可變參數時遇到宏

#define _INTSIZEOF(n)   ((sizeof(n)+sizeof(int)-1)&~(sizeof(int) - 1) )

目的是將求出n對齊後的字節數,從這裏來看應該是按照4字節的整數倍來對齊,爲什麼這個宏可以實現4字節的整數倍呢?

首先 (sizeof(n)+sizeof(int)-1) 在 sizeof(int) 時相當於( sizeof(n)+3 ) 如果 用 ( sizeof(n)+3 )/4*4, 則結果爲4字節的整數倍。

所以 ( sizeof(n)+3 )&~(sizeof(int) - 1)  應該相當於 ( sizeof(n)+3 )/4*4, 這是爲什麼呢?

~(sizeof(int) - 1)  就是 ~(4 - 1)  = = ~(3)  , 二進制 11111100

令x=n/4, y=n%4,  則 n=n/4*4+y, n/4*4是對齊後的字節數,而 m & 11111100剛好將後兩位,即餘數部分置爲了0,保留的剛好是n/4*4部分。

所以

n & ~(sizeof(int) - 1) ) 的作用是去掉n對sizeof(int)的餘數部分

((sizeof(n)+sizeof(int)-1)&~(sizeof(int) - 1) ) 的在作用是對n的字節數按照 sizeof(int) 的整數倍進行對齊(不足需要補充)。

這個宏的設計很巧妙,實際少是用位運算替代了除法操作,從而提高計算效率。


那麼爲什麼要對齊呢?

因爲在函數調用時,參數是通過堆棧進行調用的,估計系統爲了便於管理堆棧和參數,將壓入堆棧的參數的大小進行了固化,其實字節對齊在其他地方也經常使用,如結構體和類的大小等。sizeof() 獲得的僅僅是邏輯長度,並不是真實的物理長度?


另外三個和可變參數相關的宏。

#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )

v是第一個固定參數, ap 用於指向其他的可變參數, 這裏 ap = (va_list)&v + _INTSIZEOF(v) 使得ap指向第一個固定參數後面的第一個可變參數(壓入堆棧時,先壓入固定參數,再依次壓入可變參數,具體方式和硬件和系統有關),如printf(char *pformat, ....)

#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )

實現將ap指向的參數取出賦給t,並且讓p指向下一個可變參數 具體是先(ap += _INTSIZEOF(t)) 之後用 (*( t *)(ap-_INTSIZEOF(t))),設計的也很巧

#define va_end(ap) ( ap = (va_list)0 )

最後將ap指針設置爲空。

typedef char *  va_list;  va_list 就是char *類型的指針。


這些宏在stdarg.h頭文件中。









發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章