sizeof函數的使用及其在DSP中的應用
- 1 簡介
- 2 用法
-
- 2.1 基本資料類型的sizeof
- 2.2 指針變量的sizeof
- 2.3 數組的sizeof
- 2.4 結構體的sizeof
- 3 DSP中sizeof的用法
- 4 sizeof的用法問題
-
- 4.1 問題描述
- 4.2 問題分析
- 4.3 經驗總結
- 5 其他相關問題
1 簡介
sizeof是C/C++中的一個操作符(operator),簡單的說其作用就是傳回一個對象或者類型所占的記憶體位元組數。
2 用法
C語言中,對 sizeof() 的處理都是在編譯階段進行,是以它可以被當作常量表達式使用。其作用就是傳回一個對象或者類型所占的記憶體位元組數。
這裡的類型是指資料類型,比如int、long、數組、指針、結構體等。
這裡的對象可以是變量、資料類型、函數調用。
記憶體位元組數來源于儲存器中的概念。存儲器的容量是以位元組為基本機關的。也就是說一個記憶體位址代表一個位元組的存儲空間。
sizeof計算對象的大小也是轉換成對對象類型的計算,也就是說,同種類型的不同對象其sizeof值都是一緻的。sizeof對一個表達式求值,編譯器根據表達式的最終結果類型來确定大小,一般不會對表達式進行計算。
特别的,sizeof也可以對一個函數調用求值,其結果是函數傳回類型的大小,函數并不會被調用;函數、不能确定類型的表達式以及位域(bit-field)成員不能被計算sizeof值。
具體用法如下:
sizeof(type_name);//sizeof(類型);
sizeof object;//sizeof對象;
舉例說明:
int i;
sizeof(i);//ok
sizeof i;//ok
sizeof(int);//ok
sizeof int;//error
下面依次舉例介紹部分資料類型和對象的具體應用。
2.1 基本資料類型的sizeof
這裡的基本資料類型指short、int、long、float、double這樣的簡單内置資料類型,由于它們都是和系統相關的,是以在不同的系統下取值可能不同。
一般的,在32位編譯環境中,sizeof(int)的取值為4。
2.2 指針變量的sizeof
指針變量,是指可以用來存放另一個對象的位址的變量。指針變量裡面存放的是指針,即位址。在不同的系統中,位址的表示位數不同。如在32位系統中,位址是32位表示的。
當一個位元組8位時,在32為系統中,說一個儲存器的位址範圍一般是說 0x 00 00 00 00 ~ 0x 00 00 4F 00;而在16位系統中,位址是該範圍是說0x 00 00~ 0x 4F 00。
綜上,在32位計算機中,一個指針變量的sizeof傳回值通常是4,在64位系統中指針變量的sizeof的傳回值通常為8。
指針變量的在C語言中的定義是為了為指向的對象預配置設定記憶體位址。指針變量的sizeof值與指針所指的對象沒有任何關系,是以同一系統中所有的指針變量所占記憶體大小相等。
2.3 數組的sizeof
數組的sizeof值等于數組所占用的記憶體位元組數。
注意:字元串數組,最後一個還有終止符。
2.4 結構體的sizeof
結構體在記憶體中是按照一定的原則進行存儲的。
原則1:資料成員對齊規則:結構(struct或聯合union)的資料成員,第一個資料成員放在offset為0的地方,以後每個資料成員存儲的起始位置要從該成員大小的整數倍開始(比如int在32位機為4位元組,則要從4的整數倍位址開始存儲)。
原則2:結構體作為成員:如果一個結構裡有某些結構體成員,則結構體成員要從其内部最大元素大小的整數倍位址開始存儲。(struct a裡存有struct b,b裡有char,int,double等元素,那b應該從8的整數倍開始存儲。)
原則3:收尾工作:結構體的總大小,也就是sizeof的結果,必須是其内部最大成員的整數倍,不足的要補齊。
是以
1 結構體sizeof的結果不是簡單的加所有成員的位元組數相加;
2 結構體sizeof的結果和不同資料類型在結構體中的位置有關;比如:
struct A{
int a;
char b;
short c;
};
struct B{
char b;
int a;
short c;
};
在32位作業系統中,sizeof(A)的結果是8;sizeof(A)的結果是12。
這是因為在記憶體中的存儲如下:
a b c
A的記憶體布局:1111, 1*, 11
b a c
B的記憶體布局:1***, 1111, 11**
其中,*表示補充。
3 DSP中sizeof的用法
sizeof傳回的是記憶體位元組數。記憶體位元組數來源于儲存器中的概念。存儲器的容量是以位元組為基本機關的。也就是說一個記憶體位址代表一個位元組的存儲空間。
對于其他一般的處理器,一個記憶體位址是8位。但在DSP中,一個記憶體位址不一定是8位。以TI的C2000為例,一個記憶體位址是16位。
下圖為28033的記憶體映射圖:
圖中,一個記憶體位址對應16位,以L0 SARAM為例,位址0x00 8000~0x00 8800,記憶體位址長度為0x800 = 2K,而一個記憶體位址16位,是以L0 SARAM的存儲大小為2K x 16。
4 sizeof的用法問題
4.1 問題描述
在TI的C2000中,使用sizeof得到結構體的記憶體位元組數,當結構體中隻定義一個Uint16的變量時,sizeof的傳回值為1;結構體中有一個int32 和int16時,傳回值為4。
如下:
struct {
Uint32 Ver0;
Uint16 Ver1;
} infoVersion_P;
sizeof(infoVersion_P)的結果是4。
struct {
Uint16 Ver1;
} infoVersion_P1;
sizeof(infoVersion_P1)的結果是1。
4.2 問題分析
DSP使用的是28033,該晶片一個位址對應16位。是以結構體隻有Uint16一個成員的時候,sizeof的傳回值是1。
結構體在存儲的時候,記憶體對齊。是以,結構體中有一個int32 和int16時,占用的是4個位址。是以sizeof的傳回值是4。
4.3 經驗總結
要使用sizeof來傳回結構體的記憶體位元組數時,定義的結構體最好按照32位,便于後期和其他人維護。
5 其他相關問題
在查詢資料時發現,C2000中除了一個位址對應16位是非正常的,還有關于char也是非正常的。char是16位的定義。
還是以28033為例,其使用的CPU如資料手冊所示:
而該CPU中關于資料類型的定義如下:
使用編譯器甄别,分别給一個char變量指派16位和32為數值,指派16為數值,編譯器正常無問題;指派32為,編譯器報錯。是以,char确實是16位的。