void指標的轉換(2),void指標轉換
void類型指標可以通過顯式轉換為具有更小或相同儲存對齊限制的指標,但資料可能失真。所謂“相同儲存對齊限制”是指void類型指標所指的資料在記憶體中所佔的長度與顯式轉換後的指標所指的資料在記憶體中所佔的長度相等,比如以上程式中的p1所指的原資料在記憶體中佔2個位元組,p2所指的資料在記憶體中也是佔兩個資料。但應注意的是,只有上面的這種轉換前後指標所指資料類型一致的轉換才保持資料不失真,如果類型不一致,即使具有相同儲存對齊限制,也有可能失真,比如由short轉向unsigned short,請看以下程式:
#include<stdio.h>
int main(void)
{
short a=-5,*p1=&a;
unsigned short *p2;
void *p3;
p3=(void *)p1;
p2=(unsigned short *)p3;
printf("%d\n",*p2);
return 0;
}
其輸出結果就不再是-5了,因為在指標轉換時,short類型的資料也經過轉換變成了unsigned short類型的資料,具體的轉換過程請參考資料類型轉換。不過,也有數值不變的情況,如把a值變為5。
同理,如果是將void類型轉換為具有更小儲存對齊限制的指標時,也可能引起數值的改變。請看以下程式:
#include<stdio.h>
int main(void)
{
short a=720;
char *p1;
void *p2;
p2=(void *)&a;
p1=(char *)p2;
printf("%d\n",*p1);
return 0;
}
p1所指向的資料不再是720,而是-48。因為a的值720在記憶體中的表示形式為D0 02(十六進位表示,共兩塊,即兩個位元組),其中D0的地址即a的地址:0x0012ff7c,p2隻儲存0x0012ff7c,不知道它佔有兩位元組記憶體空間。而p1所指資料佔有一位元組,因此p1隻代表D0,無法代表D0 02,將D0翻譯成有符號char類型,即-48(D0是補碼)。當然,如果將a的值改為較小的數(-128~127),如3,轉換後的值變不會發生改變。
綜上兩種情況,其實void類型指標所指向的資料一直都在記憶體中存放著,並沒有被改動,而只是我們在引用時從記憶體中提取資料的過程中發生了提取錯誤。道理很簡單,一個有兩位元組組成的資料,而你非要提取一位元組,是有可能發生錯誤的(但不是一定會發生錯誤,當一個資料既能用一位元組表示,又能用兩位元組表示時就不會產生錯誤)。如果我們提取正確的話,隨時都可以得到正確的資料,比如將上面的printf("%d\n",*p1);改為printf("%d\n",*(short *)p1);則又會輸出720。
3.如果將void類型的指標轉換為具有更大儲存對齊限制的指標時,則會產生無效值。如以下程式:
#include<stdio.h>
int main(void)
{
short a=23;
void *p1;
int *p2;
p1=(void *)&a;
p2=(int *)p1;
printf("%d\n",*p2); return 0;
}
其返回值為-859045865