<menu id="w8yyk"><menu id="w8yyk"></menu></menu>
  • <dd id="w8yyk"><nav id="w8yyk"></nav></dd>
    <menu id="w8yyk"></menu>
    <menu id="w8yyk"><code id="w8yyk"></code></menu>
    <menu id="w8yyk"></menu>
    <xmp id="w8yyk">
    <xmp id="w8yyk"><nav id="w8yyk"></nav>
  • 網站首頁 > 物聯資訊 > 技術分享

    深入理解計算機各種類型大小(sizeof)

    2016-09-28 00:00:00 廣州睿豐德信息科技有限公司 閱讀
    睿豐德科技 專注RFID識別技術和條碼識別技術與管理軟件的集成項目。質量追溯系統、MES系統、金蝶與條碼系統對接、用友與條碼系統對接

    深入理解計算機各種類型大小(sizeof)

      Cpp代碼 復制代碼 收藏代碼
    1. // Example of the sizeof keyword   
    2. size_t  i = sizeofint );    
    3.   
    4. struct align_depends {   
    5.     char c;   
    6.     int i;   
    7. };   
    8. size_t size = sizeof(align_depends);  // The value of size depends on    
    9.                                    //  the value set with /Zp or    
    10.                                    //  #pragma pack   
    11.   
    12. int  array[] = { 1, 2, 3, 4, 5 };     // sizeof( array ) is 20    
    13.                                       // sizeof( array[0] ) is 4    
    14. size_t  sizearr =                        // Count of items in array   
    15.    sizeof( array ) / sizeof( array[0] );  
    // Example of the sizeof keyword
    size_t  i = sizeof( int ); 
    
    struct align_depends {
        char c;
        int i;
    };
    size_t size = sizeof(align_depends);  // The value of size depends on 
                                       //  the value set with /Zp or 
                                       //  #pragma pack
    
    int  array[] = { 1, 2, 3, 4, 5 };     // sizeof( array ) is 20 
                                          // sizeof( array[0] ) is 4 
    size_t  sizearr =                        // Count of items in array
       sizeof( array ) / sizeof( array[0] );

      <!----> <script src="ms-its:dsmsdn.chm::/html/msdn_footer.js"></script> <!---->

     

    1. 用法

    1.1 sizeof和new、delete等一樣,是關鍵字,不是函數或者宏。

    1.2 sizeof返回內存中分配的字節數,它和操作系統的位數有關。例如在常見的32位系統中,int類型占4個字節;但是在16位系統中,int類型占2個字節。

    1.3 sizeof的參數可以是類型,也可以是變量,還可以是常量。對于相同類型,以上3中形式參數的sizeof返回值相同。

    Cpp代碼 復制代碼 收藏代碼
    1. int a;   
    2. sizeof(a); // = 4   
    3. sizeof(int); // = 4   
    4. sizeof(1); // = 4  
    int a;
    sizeof(a); // = 4
    sizeof(int); // = 4
    sizeof(1); // = 4

     

    1.4 C99標準規定,函數、不能確定類型的表達式以及位域(bit-field)成員不能被計算s 
    izeof值,即下面這些寫法都是錯誤的。

    Cpp代碼 復制代碼 收藏代碼
    1. void fn() { }   
    2. sizeof(fn); // error:函數   
    3. sizeof(fn()); // error:不能確定類型   
    4. struct S   
    5. {   
    6.     int a : 3;   
    7. };    
    8. S sa;     
    9. sizeof( sa.a ); // error:位域成員  
    void fn() { }
    sizeof(fn); // error:函數
    sizeof(fn()); // error:不能確定類型
    struct S
    {
    	int a : 3;
    }; 
    S sa;  
    sizeof( sa.a ); // error:位域成員

     

    1.5 sizeof在編譯階段處理。由于sizeof不能被編譯成機器碼,所以sizeof的參數不能被編譯,而是被替換成類型。

    Cpp代碼 復制代碼 收藏代碼
    1. int a = -1;   
    2. sizeof(a=3); // = sizeof(a) = sizeof(int) = 4   
    3. cout<<a<<endl; // 輸出-1。由于“=”操作符返回左操作數的類型,賦值操作沒有執行。  
    int a = -1;
    sizeof(a=3); // = sizeof(a) = sizeof(int) = 4
    cout<<a<<endl; // 輸出-1。由于“=”操作符返回左操作數的類型,賦值操作沒有執行。

     

     

    2. 在32位系統中不同類型的內存分配

    2.1 基本類型

    Cpp代碼 復制代碼 收藏代碼
    1. sizeof(int);        // = 4   
    2. sizeof(double);     // = 8   
    3. sizeof(char);       // = 1   
    4. sizeof(bool);       // = 1   
    5. sizeof(short);      // = 2   
    6. sizeof(float);      // = 4   
    7. sizeof(long);       // = 4  
    sizeof(int);        // = 4
    sizeof(double);     // = 8
    sizeof(char);       // = 1
    sizeof(bool);       // = 1
    sizeof(short);      // = 2
    sizeof(float);      // = 4
    sizeof(long);       // = 4
    

     

    2.2 指針

    指針在32位系統中占4個字節。

    Cpp代碼 復制代碼 收藏代碼
    1. sizeof(int *);         // = 4   
    2. sizeof(double *);      // = 4   
    3. sizeof(char *);        // = 4  
    sizeof(int *);         // = 4
    sizeof(double *);      // = 4
    sizeof(char *);        // = 4
    

     

    2.3 數組

    2.3.1 數組的sizeof返回整個數組所占的字節數,即(數組元素個數×每個元素所占字節)。

    Cpp代碼 復制代碼 收藏代碼
    1. int ai[] = {1, 2};   
    2. sizeof(ai);          // = 2*4 = 8  
    int ai[] = {1, 2};
    sizeof(ai);          // = 2*4 = 8

     

    2.3.2 常量字符串與字符數組的內存分配方式相同。

    Cpp代碼 復制代碼 收藏代碼
    1. char ac[] = "abcd";  //注意數組末尾的字符串終結符'\0'   
    2. sizeof(ac);          // = 5*1 = 5   
    3. sizeof("abcd");      // = 5*1 = 5  
    char ac[] = "abcd";  //注意數組末尾的字符串終結符'\0'
    sizeof(ac);          // = 5*1 = 5
    sizeof("abcd");      // = 5*1 = 5

     

    2.3.3 數組和指針所占的字節數不同,應注意區分。

    Cpp代碼 復制代碼 收藏代碼
    1. int *pi = new int[10]; //這是指針   
    2. sizeof(pi);            // = 4   
    3.   
    4. int ai[10];   
    5. int *p = ai;           //這還是指針   
    6. sizeof(p);             // = 4   
    7.   
    8. double* (*a)[3][6];    //看成(double *) (*a)[3][6],即一個3×6的二維數組,數組元素為指針,指向double類型。   
    9. sizeof(a);             // = 4,a為指向上述二維數組的指針   
    10. sizeof(*a);            // = sizeof(double *)*3*6 = 72,*a表示上述二維數組       
    11. sizeof(**a);           // = sizeof(double *)*6 = 24,**a即*(*a),表示double*[6],是元素為double指針的一維數組。   
    12. sizeof(***a);          // = sizeof(double *) = 4,表示上述一維數組中的第一個元素,元素類型為double指針。   
    13. sizeof(****a);         // = sizeof(double) = 8,表示上述數組首元素指向的double類型。  
    int *pi = new int[10]; //這是指針
    sizeof(pi);            // = 4
    
    int ai[10];
    int *p = ai;           //這還是指針
    sizeof(p);             // = 4
    
    double* (*a)[3][6];    //看成(double *) (*a)[3][6],即一個3×6的二維數組,數組元素為指針,指向double類型。
    sizeof(a);             // = 4,a為指向上述二維數組的指針
    sizeof(*a);            // = sizeof(double *)*3*6 = 72,*a表示上述二維數組    
    sizeof(**a);           // = sizeof(double *)*6 = 24,**a即*(*a),表示double*[6],是元素為double指針的一維數組。
    sizeof(***a);          // = sizeof(double *) = 4,表示上述一維數組中的第一個元素,元素類型為double指針。
    sizeof(****a);         // = sizeof(double) = 8,表示上述數組首元素指向的double類型。
    

     

    2.3.4 函數形式參數中的數組會蛻變為指針,原因是數組參數“傳址調用”,調用者只需將實參的地址傳遞過去。有一種情況例外,那就是參數是指向數組的指針。

    Cpp代碼 復制代碼 收藏代碼
    1. void acf(char p[3])     //參數類型是int[],表示指向int的指針   
    2. {   
    3.     sizeof( p );        // = 4   
    4. }   
    5. void aif(int p[])       //參數類型是int[],表示指向int的指針   
    6. {   
    7.     sizeof( p );        // = 4   
    8. }   
    9. void pif(int (*p)[6])   //參數類型是int (*)[6],表示指向int數組的指針   
    10. {   
    11.     sizeof( p);         // = 4   
    12.     sizeof( *p );       // = sizeof(int)*6 = 24   
    13. }   
    14. void ppf(int *p[6])     //參數類型是int *[],表示指向int指針的指針   
    15. {   
    16.     sizeof( p );        // = 4   
    17.     sizeof( *p );       // = 4   
    18. }  
    void acf(char p[3])     //參數類型是int[],表示指向int的指針
    {
        sizeof( p );        // = 4
    }
    void aif(int p[])       //參數類型是int[],表示指向int的指針
    {
        sizeof( p );        // = 4
    }
    void pif(int (*p)[6])   //參數類型是int (*)[6],表示指向int數組的指針
    {
        sizeof( p);         // = 4
        sizeof( *p );       // = sizeof(int)*6 = 24
    }
    void ppf(int *p[6])     //參數類型是int *[],表示指向int指針的指針
    {
        sizeof( p );        // = 4
        sizeof( *p );       // = 4
    }
    

     

    2.4. 類和結構體的內存分配。

    2.4.1 空類或空結構體占一個字節。

    Cpp代碼 復制代碼 收藏代碼
    1. class CEmpty { };   
    2. sizeof(CEmpty); // = 1   
    3.   
    4. struct SEmpty { };   
    5. sizeof(SEmpty); // = 1  
    class CEmpty { };
    sizeof(CEmpty); // = 1
    
    struct SEmpty { };
    sizeof(SEmpty); // = 1

     

    2.4.2 非空類和結構體所占字節為所有成員占字節的和,但是不包括成員函數和靜態成員所占的空間。

    Cpp代碼 復制代碼 收藏代碼
    1. class CInt : public CEmpty {   
    2.     int i;   
    3. };   
    4. sizeof(CInt); // = 4;   
    5.   
    6. class CFunc {   
    7.     void f() {}   
    8. };   
    9. sizeof(CFunc); // = 1;   
    10.   
    11. struct SInt : SEmpty {   
    12.     static int i;   
    13. };   
    14. sizeof(SInt); // = 1;  
    class CInt : public CEmpty {
    	int i;
    };
    sizeof(CInt); // = 4;
    
    class CFunc {
    	void f() {}
    };
    sizeof(CFunc); // = 1;
    
    struct SInt : SEmpty {
    	static int i;
    };
    sizeof(SInt); // = 1;

     

    2.4.3 字節對齊

    為了加快計算機的取數速度,編譯器默認對內存進行字節對齊。對結構體(包括類)進行字節對齊的原則是:

    1)結構體變量的首地址能夠被其最寬基本類型成員的大小所整除;

    2)結構體每個成員相對于結構體首地址的偏移量(offset)都是成員大小的整數倍,如有需要編譯器會在成員之間加上填充字節(internal adding);

    3)結構體的總大小為結構體最寬基本類型成員大小的整數倍,如有需要編譯器會在最末一個成員之后加上填充字節(trailing padding)。

    Cpp代碼 復制代碼 收藏代碼
    1. struct SByte1   
    2. {   
    3.     double d;    // 偏移量0~7   
    4.     char j;      // 偏移量8   
    5.     int a;       // 偏移量12~15,由于9不能整除4,故先填充9~11   
    6. };    
    7. sizeof(SByte1);  // = 16   
    8.   
    9. struct SByte2   
    10. {         
    11.     char j;      // 偏移量0   
    12.     double d;    // 偏移量8~15,由于1不能整除8,故先填充1~7   
    13.     int a;       // 偏移量16~19   
    14. };    
    15. sizeof(SByte2);  // = 24,為了湊成8的倍數,填充20~23  
    struct SByte1
    {
    	double d;    // 偏移量0~7
    	char j;      // 偏移量8
    	int a;       // 偏移量12~15,由于9不能整除4,故先填充9~11
    }; 
    sizeof(SByte1);  // = 16
    
    struct SByte2
    {      
        char j;      // 偏移量0
    	double d;    // 偏移量8~15,由于1不能整除8,故先填充1~7
    	int a;       // 偏移量16~19
    }; 
    sizeof(SByte2);  // = 24,為了湊成8的倍數,填充20~23

     

    另外,可以通過#pragma pack(n)來設定變量以n字節對齊方式。

    Cpp代碼 復制代碼 收藏代碼
    1. #pragma pack(push) //保存對齊狀態   
    2. #pragma pack(4)    //設定為4字節對齊   
    3. class CByte   
    4. {   
    5.     char c;        //偏移量0   
    6.     double d;      //偏移量4~11,由于1不能整除4,故先填充1~3   
    7.     int i;         //偏移量12~15   
    8. };   
    9. #pragma pack(pop)  //恢復對齊狀態   
    10. sizeof(CByte); // = 16  
    #pragma pack(push) //保存對齊狀態
    #pragma pack(4)    //設定為4字節對齊
    class CByte
    {
    	char c;        //偏移量0
    	double d;      //偏移量4~11,由于1不能整除4,故先填充1~3
    	int i;         //偏移量12~15
    };
    #pragma pack(pop)  //恢復對齊狀態
    sizeof(CByte); // = 16
    

     

    2.4.4 位域

    有些信息在存儲時,并不需要占用一個完整的字節, 而只需占幾個或一個二進制位。例如在存放一個開關量時,只有0和1 兩種狀態,用一位二進位即可。為了節省存儲空間,并使處理簡便,C語言又提供了一種數據結構,稱為“位域”或“位段”。所謂“位域”是把一個字節中的二進位劃分為幾個不同的區域, 并說明每個區域的位數。

     

    2.4.4.1 位域以比特位作為單位,其長度不能大于一個字節。一個位域必須存儲在同一個字節中,如一個字節所剩空間不夠存放另一位域時,應從下一單元起存放該位域。

    Cpp代碼 復制代碼 收藏代碼
    1. struct SBit1   
    2. {   
    3.   
    4.     char a : 3;   
    5.     char b : 4;   
    6.     char c : 5;   
    7. };   
    8. sizeof(SBit1); // = (3+4+1+5+3) bits = 2 bytes  
    struct SBit1
    {
    
        char a : 3;
        char b : 4;
        char c : 5;
    };
    sizeof(SBit1); // = (3+4+1+5+3) bits = 2 bytes

    SBit1:| a × 3+ b × 4 + # × 1 | c × 5 + # × 3 |

     

    2.4.4.2 使用空域可以有意使某位域從下一單元開始,但是空域不能使用。

    Cpp代碼 復制代碼 收藏代碼
    1. struct SBit2   
    2. {   
    3.     char a : 3;   
    4.     char   : 0;   // 空域   
    5.     char b : 4;   
    6.     char c : 5;   
    7. };   
    8. sizeof(SBit2); // = (3+4+1+5+3) bits = 3 bytes  
    struct SBit2
    {
        char a : 3;
        char   : 0;   // 空域
        char b : 4;
        char c : 5;
    };
    sizeof(SBit2); // = (3+4+1+5+3) bits = 3 bytes

    SBit2:| a ×3 + # × 5 | b × 4 + # × 4 | c × 5 + # × 3 |

     

    2.4.4.3 如果相鄰的位域字段的類型不同,則各編譯器的具體實現有差異,VC6采取不壓縮方式,Dev-C++采取壓縮方式。

    Cpp代碼 復制代碼 收藏代碼
    1. struct SBit3   
    2. {   
    3.     char  a : 3;   
    4.     short b : 4;   
    5.     char  c : 5;   
    6. };   
    7. sizeof(SBit3); // = 6 bytes,由于相鄰位域類型不同,在VC6中其sizeof為6,在Dev-C++中為2。  
    struct SBit3
    {
        char  a : 3;
        short b : 4;
        char  c : 5;
    };
    sizeof(SBit3); // = 6 bytes,由于相鄰位域類型不同,在VC6中其sizeof為6,在Dev-C++中為2。

    SBit3(不壓縮):| a ×3 | # ×8 |b × 4 + # ×4 | # ×8 | c ×5 + # ×3 | # ×8 

    SBit3(壓縮):| a×3 + b ×4 + # ×1 |   c ×5 + # ×3 |

     

    2.4.4.4 如果位域字段之間穿插著非位域字段,則不進行壓縮。

    Cpp代碼 復制代碼 收藏代碼
    1. struct SBit4   
    2. {   
    3.     int a : 3;   
    4.     int b : 4;   
    5.     int c;   
    6. };   
    7. sizeof(SBit4); // = 8 bytes  
    struct SBit4
    {
        int a : 3;
        int b : 4;
        int c;
    };
    sizeof(SBit4); // = 8 bytes
    

    SBit4:| a×3 + b ×4 + # ×1 | # ×8 | # ×8 | # ×8 | c ×8 | c ×8 | c ×8 | c ×8 |

     

    2.4.4.5 整個結構體的總大小為最寬基本類型成員大小的整數倍。

    Cpp代碼 復制代碼 收藏代碼
    1. struct SBit5   
    2. {   
    3.     int a : 3;   
    4.     int b;   
    5.     int c : 5;   
    6. };   
    7. sizeof(SBit5); // = 12 bytes  
    struct SBit5
    {
        int a : 3;
        int b;
        int c : 5;
    };
    sizeof(SBit5); // = 12 bytes
    

    SBit5:| a×3 + # ×5 | # ×8 | # ×8 | # ×8 | b ×8 | b ×8 | b ×8 | b ×8 | c ×5 + # ×3 | # ×8 | # ×8 | #×8 |

     

     

    2.5 聯合

    聯合表示若干數據成員取其一,故以疊加方式分配內存,所占字節數為最大數據成員所占的字節數。

    Cpp代碼 復制代碼 收藏代碼
    1. union U   
    2. {   
    3.     int i;   
    4.     char c;   
    5.     double d;   
    6. };   
    7. sizeof(U); // = Max(sizeof(i), sizeof(c), sizeof(d)) = sizeof(d) = 8  
    RFID管理系統集成商 RFID中間件 條碼系統中間層 物聯網軟件集成
    最近免费观看高清韩国日本大全