指標型別轉換

2021-08-27 12:37:36 字數 2991 閱讀 2221

指標型別轉換

當我們初始化乙個指標或給乙個指標賦值時,賦值號的左邊是乙個指標,賦值號的右邊是乙個指標表示式。在我們前面所舉的例子中,絕大多數情況下,指標的型別和指標表示式的型別是一樣的,指標所指向的型別和指標表示式所指向的型別是一樣的。

例十四:

1、float f=12.3;

2、float*fptr=&f;

3、int*p;

在上面的例子中,假如我們想讓指標p指向實數f,應該怎麼搞?是用下面的語句嗎?

p=&f;

不對。因為指標p的型別是int*,它指向的型別是int。表示式&f的結果是乙個指標,指標的型別是float*,它指向的型別是float。兩者不一致,直接賦值的方法是不行的。至少在我的msvc++6.0上,對指標的賦值語句要求賦值號兩邊的型別一致,所指向的型別也一致,其它的編譯器上我沒試過,大家可以試試。為了實現我們的目的,需要進行"強制型別轉換":

p=(int*)&f;

如果有乙個指標p,我們需要把它的型別和所指向的型別改為tyep*type, 那麼語法格式是:

(type*)p;

這樣強制型別轉換的結果是乙個新指標,該新指標的型別是type*,它指向的型別是type,它指向的位址就是原指標指向的位址。而原來的指標p的一切屬性都沒有被修改。

乙個函式如果使用了指標作為形參,那麼在函式呼叫語句的實參和形參的結合過程中,也會發生指標型別的轉換。

例十五:

void fun(char*);

int a=125,b;

fun((char*)&a);

...

...

voidfun(char*s) }

注意這是乙個32位程式,故int型別佔了四個位元組,char型別佔乙個位元組。函式fun的作用是把乙個整數的四個位元組的順序來個顛倒。注意到了嗎?在函式呼叫語句中,實參&a的結果是乙個指標,它的型別是int*,它指向的型別是int。形參這個指標的型別是char*,它指向的型別是char。這樣,在實參和形參的結合過程中,我們必須進行一次從int*型別到char*型別的轉換。結合這個例子,我們可以這樣來想象編譯器進行轉換的過程:編譯器先構造乙個臨時指標char*temp, 然後執行temp=(char*)&a,最後再把temp的值傳遞給s。所以最後的結果是:s的型別是char*,它指向的型別是char,它指向的位址就是a的首位址。

我們已經知道,指標的值就是指標指向的位址,在32位程式中,指標的值其實是乙個32位整數。那可不可以把乙個整數當作指標的值直接賦給指標呢?就象下面的語句:

unsigned int a;

type*ptr;//type是int,char或結構型別等等型別。

...

...

a=20345686;

ptr=20345686;//我們的目的是要使指標ptr指向位址20345686(十進位制

) ptr=a;//我們的目的是要使指標ptr指向位址20345686(十進位制)

編譯一下吧。結果發現後面兩條語句全是錯的。那麼我們的目的就不能達到了嗎?不,還有辦法:

unsigned int a;

type*ptr;//type是int,char或結構型別等等型別。

...

...

a=某個數,這個數必須代表乙個合法的位址;

ptr=(type*)a;//呵呵,這就可以了。

嚴格說來這裡的(type*)和指標型別轉換中的(type*)還不一樣。這裡的(type*)的意思是把無符號整數a的值當作乙個位址來看待。上面強調了a的值必須代表乙個合法的位址,否則的話,在你使用ptr的時候,就會出現非法操作錯誤。

想想能不能反過來,把指標指向的位址即指標的值當作乙個整數取出來。完 全可以。下面的例子演示了把乙個指標的值當作乙個整數取出來,然後再把這個整數當作乙個位址賦給乙個指標:

例十六:

inta=123,b;

int*ptr=&a;

char*str;

b=(int)ptr;//把指標ptr的值當作乙個整數取出來。

str=(char*)b;//把這個整數的值當作乙個位址賦給指標str。

現在我們已經知道了,可以把指標的值當作乙個整數取出來,也可以把乙個整數值當作位址賦給乙個指標。

指標的安全問題

看下面的例子:

例十七:

char s='a';

int*ptr;

ptr=(int*)&s;

*ptr=1298;

指標ptr是乙個int*型別的指標,它指向的型別是int。它指向的位址就是s的首位址。在32位程式中,s佔乙個位元組,int型別佔四個位元組。最後一條語句不但改變了s所佔的乙個位元組,還把和s相臨的高位址方向的三個位元組也改變了。這三個位元組是幹什麼的?只有編譯程式知道,而寫程式的人是不太可能知道的。也許這三個位元組裡儲存了非常重要的資料,也許這三個位元組裡正好是程式的一條**,而由於你對指標的馬虎應用,這三個位元組的值被改變了!這會造成崩潰性的錯誤。

讓我們再來看一例:

例十八:

1、char a;

2、int*ptr=&a;

...

...

3、ptr++;

4、*ptr=115;

該例子完全可以通過編譯,並能執行。但是看到沒有?第3句對指標ptr進行自加1運算後,ptr指向了和整形變數a相鄰的高位址方向的一塊儲存區。這塊儲存區里是什麼?我們不知道。有可能它是乙個非常重要的資料,甚至可能是一條**。而第4句竟然往這片儲存區里寫入乙個資料!這是嚴重的錯誤。所以在使用指標時,程式設計師心裡必須非常清楚:我的指標究竟指向了**。在用指標訪問陣列的時候,也要注意不要超出陣列的低端和高階界限,否則也會造成類似的錯誤。

在指標的強制型別轉換:ptr1=(type*)ptr2中,如果sizeof(ptr2的型別)大於sizeof(ptr1的型別),那麼在使用指標ptr1來訪問ptr2所指向的儲存區時是安全的。如果sizeof(ptr2的型別)小於sizeof(ptr1的型別),那麼在使用指標ptr1來訪問ptr2所指向的儲存區時是不安全的。至於為什麼,讀者結合例十七來想一想,應該會明白的。

指標型別轉換

當我們初始化乙個指標或給乙個指標賦值時,賦值號的左邊是乙個指標,賦 值號的右邊是乙個指標表示式。在我們前面所舉的例子中,絕大多數情況下,指 針的型別和指標表示式的型別是一樣的,指標所指向的型別和指標表示式所指向 的型別是一樣的。例十四 1。float f 12.3 2。float fptr f 3。...

指標型別轉換

指標型別轉換 當我們初始化乙個指標或給乙個指標賦值時,賦值號的左邊是乙個指標,賦值號的右邊是乙個指標表示式。在我們前面所舉的例子中,絕大多數情況下,指標的型別和指標表示式的型別是一樣的,指標所指向的型別和指標表示式所指向的型別是一樣的。例十四 1 float f 12.3 2 float fptr ...

指標強制型別轉換

當我們初始化乙個指標或給乙個指標賦值時,賦值號的左邊是乙個指標,賦值號的右邊是乙個指標表示式。在我們前面所舉的例子中,絕大多數情況下,指標的型別和指標表示式的型別是一樣的,指標所指向的型別和指標表示式所指向的型別是一樣的。例十四 1。float f 12.3 2。float fptr f 3。int...