C語言指針強(qiáng)制類型轉(zhuǎn)換

轉(zhuǎn)載:http://blog.csdn.net/mhjcumt/article/details/7355127

//數(shù)據(jù)類型轉(zhuǎn)換分為:數(shù)值類型轉(zhuǎn)換 ?, 指針類型轉(zhuǎn)化(重新解釋內(nèi)存)辉浦;

概要:

C語言中炫隶,任何一個(gè)變量都必須占有一個(gè)地址,而這個(gè)地址空間內(nèi)的0-1代碼就是這個(gè)變量的值珊搀。不同的數(shù)據(jù)類型占有的空間大小不一脉顿,但是他們都必須有個(gè)地址糕档,而這個(gè)地址就是硬件訪問的依據(jù),而名字只是提供給程序員的一種記住這個(gè)地址的方便一點(diǎn)的方法痊硕。但是赊级,不同的變量在機(jī)器中都是0-1代碼,所以寿桨,我們不能簡單的通過檢查一個(gè)值的位來判斷它的類型此衅。

例如强戴,定義如下:

int a;

float b;

double c;

long double d;

(假設(shè)它們所占的字節(jié)分別是4、8挡鞍、8骑歹、10,而且連續(xù)存儲(chǔ)于某個(gè)地址空間墨微,起始地址是100道媚,則我們可以得到如下內(nèi)存分布)

a變量就是由以地址100開始到103結(jié)束的4個(gè)字節(jié)內(nèi)存空間內(nèi)的0-1代碼組成。b變量則是由以地址104開始到112結(jié)束的8個(gè)字節(jié)內(nèi)存空間內(nèi)的0-1代碼組成翘县。而在機(jī)器中最域,這些內(nèi)存都是連續(xù)的0-1代碼,機(jī)器并不知道100~103是整型而104~111是float型锈麸,所有這些類型都是編譯器告知的镀脂。當(dāng)我們用a時(shí),由于前面把a(bǔ)定義為int型忘伞,則編譯器知道從a的地址開始向后取4個(gè)字節(jié)再把它解釋成int型薄翅。那么(float)a,就是先按照int類型取出該數(shù)值氓奈,再將該數(shù)值按照int to float的規(guī)則轉(zhuǎn)換成float型翘魄。所以強(qiáng)制類型轉(zhuǎn)換就是按照某個(gè)變量的類型取出該變量的值,再按照***to***的規(guī)則進(jìn)行強(qiáng)制轉(zhuǎn)轉(zhuǎn)換舀奶。如果是(類型名)常數(shù)暑竟,則是將該常數(shù)按照常數(shù)to類型 的規(guī)則進(jìn)行強(qiáng)制轉(zhuǎn)換。

指針也是一個(gè)變量育勺,它自己占據(jù)一個(gè)4個(gè)字節(jié)的地址空間(由于程序的尋址空間是2^32次方但荤,即4GB,所以用4個(gè)字節(jié)表示指針就已經(jīng)能指向任何程序能夠?qū)ぶ返降目臻g了怀大,所以指針的大小為4字節(jié))纱兑,他的值是另一個(gè)東西的地址呀闻,這個(gè)東西可以是普通變量化借,結(jié)構(gòu)體,還可以是個(gè)函數(shù)等等捡多。由于蓖康,指針的大小是4字節(jié),所以垒手,我們可以將指針強(qiáng)制轉(zhuǎn)換成int型或者其他類型蒜焊。同樣,我們也可以將任何一個(gè)常數(shù)轉(zhuǎn)換成int型再賦值給指針科贬。所有的指針?biāo)嫉目臻g大小都是4字節(jié)泳梆,他們只是聲明的類型不同鳖悠,他們的值都是地址指向某個(gè)東西,他們對(duì)于機(jī)器來說沒有本質(zhì)差別优妙,他們之間可以進(jìn)行強(qiáng)制類型轉(zhuǎn)換乘综。

指針 to 指針的強(qiáng)制類型轉(zhuǎn)換是指將指針?biāo)傅膬?nèi)容的類型由原先的類型轉(zhuǎn)換為后面的類型。

int a = 1;

int *p = &a;

float *p1 = (float*)p;

則p和p1的值都是&a套硼,但是*p是將&a地址中的值按照int型變量進(jìn)行解釋卡辰,而*p1則是將&a地址中的值按照float型變量進(jìn)行解釋。

鑒于指針之間這種靈活的強(qiáng)制類型轉(zhuǎn)換的需求和出于簡化代碼的考慮邪意,ANSI C引入了空指針即void*九妈。void指針又名萬能指針,在現(xiàn)在的很多程序中雾鬼,當(dāng)參數(shù)不確定時(shí)就用萬能指針代替萌朱,這一類的指針在線程\進(jìn)程函數(shù)里特別常見。

ANSI C規(guī)定策菜,void指針可以復(fù)制給其他任意類型的指針嚷兔,其他任意類型的指針也可以復(fù)制給void指針,他們之間復(fù)制不需要強(qiáng)制類型轉(zhuǎn)換做入。當(dāng)然任何地址也可以復(fù)制給void型指針冒晰。我們在《網(wǎng)絡(luò)編程》中經(jīng)常會(huì)看到accept(socket, (struct sockaddr *)&saddr_c, &lenth)之類的語句在&saddr_c之前需要增加代碼(struct sockaddr *)是因?yàn)楫?dāng)此函數(shù)被設(shè)計(jì)的時(shí)候ANSI C還沒有提出void*的概念。所有的地址統(tǒng)一用struct sockaddr類型標(biāo)識(shí)竟块,該函數(shù)的第二個(gè)參數(shù)也是指向struct sockaddr類型的指針壶运,此處是強(qiáng)制類型轉(zhuǎn)換。

當(dāng)然浪秘,在某些編譯器中不同類型的指針也可以進(jìn)行直接賦值蒋情,但一般情況下會(huì)給出類型不匹配的警告。要求程序員顯示的給出指針強(qiáng)制類型轉(zhuǎn)換可以提醒程序員小心使用指針耸携,對(duì)于明確程序目的具有一定的好處棵癣。

1、指針類型強(qiáng)制轉(zhuǎn)換:

int m;

int *pm = &m;

char *cp = (char *)&m;

pm指向一個(gè)整型夺衍,cp指向整型數(shù)的第一個(gè)字節(jié)

2狈谊、結(jié)構(gòu)體之間的強(qiáng)制轉(zhuǎn)換

struct str1 a;

struct str2 b;

a=(struct str1) b; ? ? ? ? ? ? ? ? ?//this is wrong

a=*((struct str1*)&b); ? ? ? ? //this is correct

3、關(guān)于一個(gè)程序的解釋

int main(void)

{

int a[4] = {1, 2, 3, 4};

int *ptr1=(int *)(&a+1);

int *ptr2=(int *)((int)a+1);

int *c = *(a + 1);

printf("%x, %x,%x\n", ptr1[-1], *ptr2,*c);

return 0;

}

輸出分別為4 和2000000,2

式子&a+1表示的是指針加法運(yùn)算沟沙,而不是普通的數(shù)值加法運(yùn)算

vs2008下河劝,其中a = 0x001bfc18

(&a + 1) = 0x001bfc28

而 a+1 = 0x001bfc1c

&a + 1 的值取決于a的類型如果a申明int a;

則&a + 1 = 0xFFFF5704 ?= a + 1

如果 int a(ArryLen);

則&a + 1 = 0xFFFF5700 + 4 * ArryLen <> a + 1

a 表示數(shù)組的起始地址,(int ) a 表示將a的地址轉(zhuǎn)化為一個(gè)整形數(shù)矛紫,(int)a + 1 表示普通的數(shù)值加法運(yùn)算赎瞎,(int *)((int)a + 1)表示把(int )a + 1轉(zhuǎn)化為整型指針的地址。該地址指向數(shù)組a(0)的第一個(gè)字節(jié)(從0計(jì)數(shù))颊咬,因?yàn)槭莍nt型的 所以需要四個(gè)字節(jié)的解釋务甥,所以結(jié)果是a(0)的后三個(gè)字節(jié)和a(1)的第一個(gè)字節(jié)組成的值牡辽,該值受大小端的影響。

*(a + 1) ?此時(shí)的a已經(jīng)是一個(gè)常指針了敞临,這個(gè)表達(dá)式計(jì)算出a所指向元素后面的第2個(gè)元素的地址催享,然后對(duì)它解引用得到相應(yīng)的值。這個(gè)表達(dá)式等價(jià)于

int last = a[1]

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末哟绊,一起剝皮案震驚了整個(gè)濱河市因妙,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌票髓,老刑警劉巖攀涵,帶你破解...
    沈念sama閱讀 212,294評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異洽沟,居然都是意外死亡以故,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,493評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門裆操,熙熙樓的掌柜王于貴愁眉苦臉地迎上來怒详,“玉大人,你說我怎么就攤上這事踪区±ニ福” “怎么了?”我有些...
    開封第一講書人閱讀 157,790評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵缎岗,是天一觀的道長静尼。 經(jīng)常有香客問我,道長传泊,這世上最難降的妖魔是什么鼠渺? 我笑而不...
    開封第一講書人閱讀 56,595評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮眷细,結(jié)果婚禮上拦盹,老公的妹妹穿的比我還像新娘。我一直安慰自己溪椎,他們只是感情好普舆,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,718評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著池磁,像睡著了一般奔害。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上地熄,一...
    開封第一講書人閱讀 49,906評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音芯杀,去河邊找鬼端考。 笑死雅潭,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的却特。 我是一名探鬼主播扶供,決...
    沈念sama閱讀 39,053評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼裂明!你這毒婦竟也來了椿浓?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,797評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤闽晦,失蹤者是張志新(化名)和其女友劉穎扳碍,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體仙蛉,經(jīng)...
    沈念sama閱讀 44,250評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡笋敞,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,570評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了荠瘪。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片夯巷。...
    茶點(diǎn)故事閱讀 38,711評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖哀墓,靈堂內(nèi)的尸體忽然破棺而出趁餐,到底是詐尸還是另有隱情,我是刑警寧澤篮绰,帶...
    沈念sama閱讀 34,388評(píng)論 4 332
  • 正文 年R本政府宣布澎怒,位于F島的核電站,受9級(jí)特大地震影響阶牍,放射性物質(zhì)發(fā)生泄漏喷面。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,018評(píng)論 3 316
  • 文/蒙蒙 一走孽、第九天 我趴在偏房一處隱蔽的房頂上張望惧辈。 院中可真熱鬧,春花似錦磕瓷、人聲如沸盒齿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,796評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽边翁。三九已至,卻和暖如春硕盹,著一層夾襖步出監(jiān)牢的瞬間符匾,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,023評(píng)論 1 266
  • 我被黑心中介騙來泰國打工瘩例, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留啊胶,地道東北人甸各。 一個(gè)月前我還...
    沈念sama閱讀 46,461評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像焰坪,于是被迫代替她去往敵國和親趣倾。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,595評(píng)論 2 350

推薦閱讀更多精彩內(nèi)容