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

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

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

概要:

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

例如,定義如下:

int a;

float b;

double c;

long double d;

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

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

指針也是一個變量,它自己占據(jù)一個4個字節(jié)的地址空間(由于程序的尋址空間是2^32次方,即4GB,所以用4個字節(jié)表示指針就已經(jīng)能指向任何程序能夠?qū)ぶ返降目臻g了,所以指針的大小為4字節(jié)),他的值是另一個東西的地址,這個東西可以是普通變量,結(jié)構體,還可以是個函數(shù)等等。由于,指針的大小是4字節(jié),所以,我們可以將指針強制轉(zhuǎn)換成int型或者其他類型。同樣,我們也可以將任何一個常數(shù)轉(zhuǎn)換成int型再賦值給指針。所有的指針所占的空間大小都是4字節(jié),他們只是聲明的類型不同,他們的值都是地址指向某個東西,他們對于機器來說沒有本質(zhì)差別,他們之間可以進行強制類型轉(zhuǎn)換。

指針 to 指針的強制類型轉(zhuǎn)換是指將指針所指的內(nèi)容的類型由原先的類型轉(zhuǎn)換為后面的類型。

int a = 1;

int *p = &a;

float *p1 = (float*)p;

則p和p1的值都是&a,但是*p是將&a地址中的值按照int型變量進行解釋,而*p1則是將&a地址中的值按照float型變量進行解釋。

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

ANSI C規(guī)定,void指針可以復制給其他任意類型的指針,其他任意類型的指針也可以復制給void指針,他們之間復制不需要強制類型轉(zhuǎn)換。當然任何地址也可以復制給void型指針。我們在《網(wǎng)絡編程》中經(jīng)常會看到accept(socket, (struct sockaddr *)&saddr_c, &lenth)之類的語句在&saddr_c之前需要增加代碼(struct sockaddr *)是因為當此函數(shù)被設計的時候ANSI C還沒有提出void*的概念。所有的地址統(tǒng)一用struct sockaddr類型標識,該函數(shù)的第二個參數(shù)也是指向struct sockaddr類型的指針,此處是強制類型轉(zhuǎn)換。

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

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

int m;

int *pm = &m;

char *cp = (char *)&m;

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

2、結(jié)構體之間的強制轉(zhuǎn)換

struct str1 a;

struct str2 b;

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

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

3、關于一個程序的解釋

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表示的是指針加法運算,而不是普通的數(shù)值加法運算

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)化為一個整形數(shù),(int)a + 1 表示普通的數(shù)值加法運算,(int *)((int)a + 1)表示把(int )a + 1轉(zhuǎn)化為整型指針的地址。該地址指向數(shù)組a(0)的第一個字節(jié)(從0計數(shù)),因為是int型的 所以需要四個字節(jié)的解釋,所以結(jié)果是a(0)的后三個字節(jié)和a(1)的第一個字節(jié)組成的值,該值受大小端的影響。

*(a + 1) ?此時的a已經(jīng)是一個常指針了,這個表達式計算出a所指向元素后面的第2個元素的地址,然后對它解引用得到相應的值。這個表達式等價于

int last = a[1]

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

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