青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

posts - 297,  comments - 15,  trackbacks - 0

前向聲明:
    sizeof,一個其貌不揚的家伙,引無數(shù)菜鳥竟折腰,小蝦我當初也沒少犯迷糊,秉著“辛苦我一個,幸福千萬人”的偉大思想,我決定將其盡可能詳細的總結一下。
    但當我總結的時候才發(fā)現(xiàn),這個問題既可以簡單,又可以復雜,所以本文有的地方并不適合初學者,甚至都沒有必要大作文章。但如果你想“知其然,更知其所以然”的話,那么這篇文章對你或許有所幫助。
    菜鳥我對C++的掌握尚未深入,其中不乏錯誤,歡迎各位指正啊

1. 定義:
    sizeof是何方神圣sizeof乃C/C++中的一個操作符(operator)是也,簡單的說其作用就是返回一個對象或者類型所占的內(nèi)存字節(jié)數(shù)。

MSDN上的解釋為:
The sizeof keyword gives the amount of storage, in bytes,

associated with a variable or a type (including aggregate

types). This keyword returns a value of type size_t.
    其返回值類型為size_t,在頭文件stddef.h中定義。這是一個依賴于編譯系統(tǒng)的值,一般定義為
typedef unsigned int size_t;
    世上編譯器林林總總,但作為一個規(guī)范,它們都會保證char、signed char和unsigned
char的sizeof值為1,畢竟char是我們編程能用的最小數(shù)據(jù)類型。

2. 語法:
    sizeof有三種語法形式,如下:
    1) sizeof( object ); // sizeof( 對象 );
    2) sizeof( type_name ); // sizeof( 類型 );
    3) sizeof object; // sizeof 對象;
所以,
int i;
sizeof( i ); // ok
sizeof i; // ok
sizeof( int ); // ok
sizeof int; // error
    既然寫法3可以用寫法1代替,為求形式統(tǒng)一以及減少我們大腦的負擔,第3種寫法,忘掉它吧!實際上,sizeof計算對象的大小也是轉(zhuǎn)換成對對象類型的計算,也就是說,同種類型的不同對象其sizeof值都是一致的。這里,對象可以進一步延伸至表達式,即sizeof可以對一個表達式求值,編譯器根據(jù)表達式的最終結果類型來確定大小,一般不會對表達式進行計算。如:
sizeof( 2 ); // 2的類型為int,所以等價于 sizeof( int );
sizeof( 2 + 3.14 );  // 3.14的類型為double,2也會被提升成double類型,所以等價于 sizeof( double );

    sizeof也可以對一個函數(shù)調(diào)用求值,其結果是函數(shù)返回類型的大小,函數(shù)并不會被調(diào)用,我們來看一個完整的例子:
char foo()
{
    printf("foo() has been called.\n");
    return 'a';
}
int main()
{
    size_t sz = sizeof( foo() ); // foo() 的返回值類型為char,所以sz = sizeof(char ),foo()并不會被調(diào)用
    printf("sizeof( foo() ) = %d\n", sz);
}

    C99標準規(guī)定,函數(shù)、不能確定類型的表達式以及位域(bit-field)成員不能被計算sizeof值,即下面這些寫法都是錯誤的:
    sizeof( foo );// error
    void foo2() { }
    sizeof( foo2() );// error
    struct S
    {
        unsigned int f1 : 1;
        unsigned int f2 : 5;
        unsigned int f3 : 12;
    };
    sizeof( S.f1 );// error

3. sizeof的常量性
    sizeof的計算發(fā)生在編譯時刻,所以它可以被當作常量表達式使用,如:
char ary[ sizeof( int ) * 10 ]; // ok
    最新的C99標準規(guī)定sizeof也可以在運行時刻進行計算,如下面的程序在Dev-C++中可以正確執(zhí)行:
int n;
n = 10; // n動態(tài)賦值
char ary[n]; // C99也支持數(shù)組的動態(tài)定義
printf("%d\n", sizeof(ary)); // ok. 輸出10
    但在沒有完全實現(xiàn)C99標準的編譯器中就行不通了,上面的代碼在VC6中就通不過編譯。所以我們最好還是認為sizeof是在編譯期執(zhí)行的,這樣不會帶來錯誤,讓程序的可移植性強些。

4. 基本數(shù)據(jù)類型的sizeof
    這里的基本數(shù)據(jù)類型指short、int、long、float、double這樣的簡單內(nèi)置數(shù)據(jù)類型,由于它們都是和系統(tǒng)相關的,所以在不同的系統(tǒng)下取值可能不同,這務必引起我們的注意,盡量不要在這方面給自己程序的移植造成麻煩。
    一般的,在32位編譯環(huán)境中,sizeof(int)的取值為4。

5. 指針變量的sizeof
    學過數(shù)據(jù)結構的你應該知道指針是一個很重要的概念,它記錄了另一個對象的地址。既然是來存放地址的,那么它當然等于計算機內(nèi)部地址總線的寬度。所以在32位計算機中,一個指針變量的返回值必定是4(注意結果是以字節(jié)為單位),可以預計,在將來的64位系統(tǒng)中指針變量的sizeof結果為8。

char* pc = "abc";
int* pi;
string* ps;
char** ppc = &pc;
void (*pf)();// 函數(shù)指針
sizeof( pc ); // 結果為4
sizeof( pi ); // 結果為4
sizeof( ps ); // 結果為4
sizeof( ppc ); // 結果為4
sizeof( pf );// 結果為4
    指針變量的sizeof值與指針所指的對象沒有任何關系,正是由于所有的指針變量所占內(nèi)存大小相等,所以MFC消息處理函數(shù)使用兩個參數(shù)WPARAM、LPARAM就能傳遞各種復雜的消息結構(使用指向結構體的指針)。

6. 數(shù)組的sizeof
    數(shù)組的sizeof值等于數(shù)組所占用的內(nèi)存字節(jié)數(shù),如:
char a1[] = "abc";
int a2[3];
sizeof( a1 ); // 結果為4,字符 末尾還存在一個NULL終止符
sizeof( a2 ); // 結果為3*4=12(依賴于int)

    一些朋友剛開始時把sizeof當作了求數(shù)組元素的個數(shù),現(xiàn)在,你應該知道這是不對的,那么應該怎么求數(shù)組元素的個數(shù)呢Easy,通常有下面兩種寫法:
int c1 = sizeof( a1 ) / sizeof( char ); // 總長度/單個元素的長度
int c2 = sizeof( a1 ) / sizeof( a1[0] ); // 總長度/第一個元素的長度

    寫到這里,提一問,下面的c3,c4值應該是多少呢
void foo3(char a3[3])
{
    int c3 = sizeof( a3 ); // c3 ==
}
void foo4(char a4[])
{
    int c4 = sizeof( a4 ); // c4 ==
}
    也許當你試圖回答c4的值時已經(jīng)意識到c3答錯了,是的,c3!=3。這里函數(shù)參數(shù)a3已不再是數(shù)組類型,而是蛻變成指針,相當于char* a3,為什么仔細想想就不難明白,我們調(diào)用函數(shù)foo1時,程序會在棧上分配一個大小為3的數(shù)組嗎不會!數(shù)組是“傳址”的,調(diào)用者只需將實參的地址傳遞過去,所以a3自然為指針類型(char*),c3的值也就為4。

7. 結構體的sizeof
    這是初學者問得最多的一個問題,所以這里有必要多費點筆墨。讓我們先看一個結構體:
struct S1
{
    char c;
    int i;
};
    問sizeof(s1)等于多少聰明的你開始思考了,char占1個字節(jié),int占4個字節(jié),那么加起來就應該是5。是這樣嗎你在你機器上試過了嗎也許你是對的,但很可能你是錯的!VC6中按默認設置得到的結果為8。

    Why為什么受傷的總是我
    請不要沮喪,我們來好好琢磨一下sizeof的定義——sizeof的結果等于對象或者類型所占的內(nèi)存字節(jié)數(shù),好吧,那就讓我們來看看S1的內(nèi)存分配情況:
S1 s1 = { 'a', 0xFFFFFFFF };
    定義上面的變量后,加上斷點,運行程序,觀察s1所在的內(nèi)存,你發(fā)現(xiàn)了什么
    以我的VC6.0為例,s1的地址為0x0012FF78,其數(shù)據(jù)內(nèi)容如下:
    0012FF78: 61 CC CC CC FF FF FF FF

    發(fā)現(xiàn)了什么怎么中間夾雜了3個字節(jié)的CC看看MSDN上的說明:
When applied to a structure type or variable, sizeof returns the actual size, which may include padding bytes inserted for alignment.
    原來如此,這就是傳說中的字節(jié)對齊啊!一個重要的話題出現(xiàn)了。
    為什么需要字節(jié)對齊計算機組成原理教導我們這樣有助于加快計算機的取數(shù)速度,否則就得多花指令周期了。為此,編譯器默認會對結構體進行處理(實際上其它地方的數(shù)據(jù)變量也是如此),讓寬度為2的基本數(shù)據(jù)類型(short等)都位于能被2整除的地址上,讓寬度為4的基本數(shù)據(jù)類型(int等)都位于能被4整除的地址上,以此類推。這樣,兩個數(shù)中間就可能需要加入填充字節(jié),所以整個結構體的sizeof值就增長了。
    讓我們交換一下S1中char與int的位置:
struct S2
{
    int i;
    char c;
};
    看看sizeof(S2)的結果為多少,怎么還是8再看看內(nèi)存,原來成員c后面仍然有3個填充字節(jié),這又是為什么啊別著急,下面總結規(guī)律。

    字節(jié)對齊的細節(jié)和編譯器實現(xiàn)相關,但一般而言,滿足三個準則:
    1) 結構體變量的首地址能夠被其最寬基本類型成員的大小所整除;
    2) 結構體每個成員相對于結構體首地址的偏移量(offset)都是成員大小的整數(shù)倍,如有需要編譯器會在成員之間加上填充字節(jié)(internal adding);
    3) 結構體的總大小為結構體最寬基本類型成員大小的整數(shù)倍,如有需要編譯器會在最末一個成員之后加上填充字節(jié)(trailing padding)。

    對于上面的準則,有幾點需要說明:
    1) 前面不是說結構體成員的地址是其大小的整數(shù)倍,怎么又說到偏移量了呢因為有了第1點存在,所以我們就可以只考慮成員的偏移量,這樣思考起來簡單。想想為什么。

    結構體某個成員相對于結構體首地址的偏移量可以通過宏offsetof()來獲得,這個宏也在stddef.h中定義,如下:
  #define offsetof(s,m) (size_t)&(((s *)0)->m)
    例如,想要獲得S2中c的偏移量,方法為
size_t pos = offsetof(S2, c);// pos等于4

    2) 基本類型是指前面提到的像char、short、int、float、double這樣的內(nèi)置數(shù)據(jù)類型,這里所說的“數(shù)據(jù)寬度”就是指其sizeof的大小。由于結構體的成員可以是復合類型,比如另外一個結構體,所以在尋找最寬基本類型成員時,應當包括復合類型成員的子成員,而不是把復合成員看成是一個整體。但在確定復合類型成員的偏移位置時則是將復合類型作為整體看待。
    這里敘述起來有點拗口,思考起來也有點撓頭,還是讓我們看看例子吧(具體數(shù)值仍以VC6為例,以后不再說明):
struct S3
{
    char c1;
    S1 s;
    char c2;
};
    S1的最寬簡單成員的類型為int,S3在考慮最寬簡單類型成員時是將S1“打散”看的,所以S3的最寬簡單類型為int,這樣,通過S3定義的變量,其存儲空間首地址需要被4整除,整個sizeof(S3)的值也應該被4整除。
    c1的偏移量為0,s的偏移量呢這時s是一個整體,它作為結構體變量也滿足前面三個準則,所以其大小為8,偏移量為4,c1與s之間便需要3個填充字節(jié),而c2與s之間就不需要了,所以c2的偏移量為12,算上c2的大小為13,13是不能被4整除的,這樣末尾還得補上3個填充字節(jié)。最后得到sizeof(S3)的值為16。

    通過上面的敘述,我們可以得到一個公式:
    結構體的大小等于最后一個成員的偏移量加上其大小再加上末尾的填充字節(jié)數(shù)目,即:

sizeof( struct ) = offsetof( last item ) + sizeof( last item ) + sizeof( trailing padding )

    到這里,朋友們應該對結構體的sizeof有了一個全新的認識,但不要高興得太早,有一個影響sizeof的重要參量還未被提及,那便是編譯器的pack指令。它是用來調(diào)整結構體對齊方式的,不同編譯器名稱和用法略有不同,VC6中通過#pragma pack實現(xiàn),也可以直接修改/Zp編譯開關。#pragma pack的基本用法為:#pragma pack( n ),n為字節(jié)對齊數(shù),其取值為1、2、4、8、16,默認是8,如果這個值比結構體成員的sizeof值小,那么
該成員的偏移量應該以此值為準,即是說,結構體成員的偏移量應該取二者的最小值,
公式如下:
offsetof( item ) = min( n, sizeof( item ) )
    再看示例:
#pragma pack(push)  // 將當前pack設置壓棧保存
#pragma pack(2) // 必須在結構體定義之前使用
struct S1
{
    char c;
    int i;
};
struct S3
{
    char c1;
    S1 s;
    char c2;
};
#pragma pack(pop) // 恢復先前的pack設置
    計算sizeof(S1)時,min(2, sizeof(i))的值為2,所以i的偏移量為2,加上sizeof(i)等于6,能夠被2整除,所以整個S1的大小為6。
    同樣,對于sizeof(S3),s的偏移量為2,c2的偏移量為8,加上sizeof(c2)等于9,不能被2整除,添加一個填充字節(jié),所以sizeof(S3)等于10。
   
    現(xiàn)在,朋友們可以輕松的出一口氣了,:)
    還有一點要注意,“空結構體”(不含數(shù)據(jù)成員)的大小不為0,而是1。試想一個“不占空間”的變量如何被取地址、兩個不同的“空結構體”變量又如何得以區(qū)分呢于是,“空結構體”變量也得被存儲,這樣編譯器也就只能為其分配一個字節(jié)的空間用于占位了。如下:
struct S5 { };
sizeof( S5 ); // 結果為1

8. 含位域結構體的sizeof
    前面已經(jīng)說過,位域成員不能單獨被取sizeof值,我們這里要討論的是含有位域的結構體的sizeof,只是考慮到其特殊性而將其專門列了出來。
    C99規(guī)定int、unsigned int和bool可以作為位域類型,但編譯器幾乎都對此作了擴展,允許其它類型類型的存在。使用位域的主要目的是壓縮存儲,其大致規(guī)則為:
    1) 如果相鄰位域字段的類型相同,且其位寬之和小于類型的sizeof大小,則后面的字段將緊鄰前一個字段存儲,直到不能容納為止;
    2) 如果相鄰位域字段的類型相同,但其位寬之和大于類型的sizeof大小,則后面的字段將從新的存儲單元開始,其偏移量為其類型大小的整數(shù)倍;
    3) 如果相鄰的位域字段的類型不同,則各編譯器的具體實現(xiàn)有差異,VC6采取不壓縮方式,Dev-C++采取壓縮方式;
    4) 如果位域字段之間穿插著非位域字段,則不進行壓縮;
    5) 整個結構體的總大小為最寬基本類型成員大小的整數(shù)倍。

    還是讓我們來看看例子。
    示例1:
struct BF1
{
    char f1 : 3;
    char f2 : 4;
    char f3 : 5;
};
    其內(nèi)存布局為:
|_f1__|__f2__|_|____f3___|____|
|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|
0 3 7 8 1316
    位域類型為char,第1個字節(jié)僅能容納下f1和f2,所以f2被壓縮到第1個字節(jié)中,而f3只
能從下一個字節(jié)開始。因此sizeof(BF1)的結果為2。

    示例2:
struct BF2
{
    char f1 : 3;
    short f2 : 4;
    char f3 : 5;
};
    由于相鄰位域類型不同,在VC6中其sizeof為6,在Dev-C++中為2。

    示例3:
struct BF3
{
    char f1 : 3;
    char f2;
    char f3 : 5;
};
    非位域字段穿插在其中,不會產(chǎn)生壓縮,在VC6和Dev-C++中得到的大小均為3。

9. 聯(lián)合體的sizeof
    結構體在內(nèi)存組織上是順序式的,聯(lián)合體則是重疊式,各成員共享一段內(nèi)存,所以整個聯(lián)合體的sizeof也就是每個成員sizeof的最大值。結構體的成員也可以是復合類型,這里,復合類型成員是被作為整體考慮的。
    所以,下面例子中,U的sizeof值等于sizeof(s)。
union U
{
    int i;
    char c;
    S1 s;
};

posted on 2008-08-19 23:51 chatler 閱讀(145) 評論(0)  編輯 收藏 引用 所屬分類: C++_BASIS
<2009年11月>
25262728293031
1234567
891011121314
15161718192021
22232425262728
293012345

常用鏈接

留言簿(10)

隨筆分類(307)

隨筆檔案(297)

algorithm

Books_Free_Online

C++

database

Linux

Linux shell

linux socket

misce

  • cloudward
  • 感覺這個博客還是不錯,雖然做的東西和我不大相關,覺得看看還是有好處的

network

OSS

  • Google Android
  • Android is a software stack for mobile devices that includes an operating system, middleware and key applications. This early look at the Android SDK provides the tools and APIs necessary to begin developing applications on the Android platform using the Java programming language.
  • os161 file list

overall

搜索

  •  

最新評論

閱讀排行榜

評論排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            一本色道久久综合| 最新成人av网站| 欧美高潮视频| 久久久久国内| 欧美精品一线| 欧美激情久久久| 韩国精品一区二区三区| 亚洲视频在线观看三级| 亚洲免费av电影| 免费在线播放第一区高清av| 久久免费一区| 国际精品欧美精品| 午夜一区在线| 久久国产加勒比精品无码| 欧美日韩在线第一页| 亚洲国内在线| 亚洲精品视频二区| 欧美va亚洲va香蕉在线| 蜜桃av一区二区三区| 激情文学一区| 久久久国产亚洲精品| 久久青草久久| 一区二区三区我不卡| 久久美女性网| 欧美国产1区2区| 亚洲国产日韩欧美一区二区三区| 久久夜色精品国产亚洲aⅴ| 老司机成人网| 亚洲国产老妈| 欧美激情亚洲一区| 亚洲国产成人av| 日韩视频―中文字幕| 欧美理论片在线观看| 日韩香蕉视频| 亚洲在线观看视频| 国产麻豆91精品| 久久精品欧美日韩精品| 欧美91福利在线观看| 亚洲日本电影在线| 欧美女同在线视频| 亚洲视频精选在线| 久久久亚洲一区| 亚洲国产婷婷综合在线精品| 欧美电影免费观看大全| 亚洲最黄网站| 久久精品成人欧美大片古装| 一区二区在线观看视频在线观看| 久久躁狠狠躁夜夜爽| 亚洲国产一区视频| 亚洲在线一区| 伊人久久综合97精品| 欧美激情一区二区三区高清视频| 一个色综合av| 久久精品人人做人人综合| 在线观看一区| 欧美视频中文字幕在线| 久久精品1区| 日韩午夜免费视频| 久久久人成影片一区二区三区观看| 在线免费观看日本一区| 国产精品av久久久久久麻豆网| 校园春色综合网| 亚洲片在线观看| 久久久www成人免费精品| 日韩视频在线一区二区| 国产手机视频精品| 欧美久久久久久蜜桃| 久久国产精品72免费观看| 亚洲激情黄色| 久久综合成人精品亚洲另类欧美| 一区二区三区国产精华| 黄色工厂这里只有精品| 欧美日韩国产专区| 久久久夜夜夜| 午夜国产一区| 亚洲毛片播放| 欧美成年视频| 久久久福利视频| 亚洲一二三区精品| 亚洲国产精品悠悠久久琪琪| 国产精品网曝门| 欧美日韩国产高清视频| 久久女同精品一区二区| 亚洲欧美成人网| 99人久久精品视频最新地址| 亚洲丶国产丶欧美一区二区三区| 久久精品国产欧美激情| 亚洲自拍三区| 一区二区av在线| 最新成人av网站| 在线观看成人一级片| 国产亚洲欧美另类中文| 国产精品毛片| 国产精品国产自产拍高清av| 欧美激情网友自拍| 欧美成人伊人久久综合网| 久久久人人人| 久久久久久久高潮| 欧美有码在线观看视频| 欧美一级日韩一级| 亚洲一区免费| 亚洲男人影院| 亚洲一区二区精品| 一本不卡影院| 亚洲天堂成人在线观看| 99综合在线| 国产精品99久久久久久久vr | 久久久久久国产精品mv| 欧美亚洲一区三区| 亚洲欧美影院| 欧美一级免费视频| 久久国产福利| 久久久久九九九九| 久久免费午夜影院| 农村妇女精品| 亚洲国产美女| 亚洲啪啪91| 一区二区欧美精品| 亚洲专区欧美专区| 久久成人国产| 蜜臀91精品一区二区三区| 欧美91视频| 国产精品sm| 国产日韩精品综合网站| 激情懂色av一区av二区av| 亚洲国产精品一区二区第四页av| 亚洲激情一区二区| 亚洲图片欧洲图片日韩av| 性伦欧美刺激片在线观看| 久久婷婷久久| 亚洲国产一区二区a毛片| 制服丝袜激情欧洲亚洲| 欧美一区国产在线| 欧美成人免费va影院高清| 欧美日韩国产综合视频在线观看| 国产精品美女久久久浪潮软件 | 亚洲国产精品va| 亚洲麻豆国产自偷在线| 亚洲欧美另类中文字幕| 久久综合福利| 亚洲精品综合| 羞羞答答国产精品www一本| 快播亚洲色图| 国产精品v日韩精品| 狠狠色丁香久久婷婷综合丁香| 日韩视频免费观看| 欧美在线亚洲在线| 亚洲激情社区| 欧美一级在线视频| 欧美人与性禽动交情品| 国产亚洲一区在线播放| 日韩性生活视频| 久久久亚洲国产美女国产盗摄| 91久久黄色| 久久国产视频网| 欧美三级日本三级少妇99| 在线观看一区视频| 午夜影院日韩| 亚洲欧洲午夜| 久久躁日日躁aaaaxxxx| 国产精品一卡二| 亚洲最新在线| 男女精品视频| 欧美综合国产| 国产精品网站视频| 一本久久综合亚洲鲁鲁五月天| 久久久不卡网国产精品一区| 99在线视频精品| 欧美大片在线观看一区| 精品av久久久久电影| 午夜久久久久久| 亚洲精品中文字| 欧美freesex8一10精品| 在线观看欧美| 久久久久久电影| 亚洲欧美激情一区| 国产精品国产三级国产aⅴ无密码| 亚洲日本成人在线观看| 能在线观看的日韩av| 久久精品国产999大香线蕉| 国产精品视频观看| 亚洲欧美成人精品| 亚洲少妇最新在线视频| 欧美日韩精品在线| 99国产精品久久久久老师| 亚洲第一偷拍| 欧美成人日韩| 亚洲精品永久免费| 亚洲福利在线视频| 欧美aa在线视频| 亚洲精品国产欧美| 亚洲高清自拍| 欧美激情无毛| aa级大片欧美三级| 日韩视频免费观看高清在线视频| 欧美欧美在线| 国产精品99久久99久久久二8 | 欧美专区在线| 韩日成人在线| 欧美11—12娇小xxxx|