關於強制轉換

1. a和&a的區別:
&a是整個數組的首地址,a是數組首元素的首地址,其值相同,但是意義不同。
eg:
char a[5] = {'A','B','C','D'};
char (*p1)[5] = &a; //沒有問題,char (*p1)[5]是數組指針,指向數組a[5]的首地址。
char (*p2)[5] = a; //編譯出錯,提示類型無法從“char [5]”轉換爲“char (*)[5]。
需要把a進行強制轉化:(char (*)[5])a;
其中:
char (*p1)[5] = &a; //p1指向地址爲0x0012ff58;
p1++; //p1此時指向地址爲0x0012ff5D;
備註:p1 + 5*sizeof(數組元素類型)
p1++操作越過了這個char a[5]數組的地址範圍。

2. 強制轉化
eg:
struct Test
{
   int Num;
   char *pcName;
   short sDate;
   char ch[2];
   short sBa[4];
}*p;
假設p的值爲0x100000,那麼如下表達式的值分別爲多少?
a. p + 0x1 = 0x????
b. (unsigned long)p + 0x1 = 0x????
c. (unsigned int*)p + 0x1 = 0x????
a: 我們會遇到一個誤區,那就是指針變量與一個整數相加減的問題,並不是我們想象
的那樣用指針變量裏的地址直接加減這個整數,這個整數的單位不是byte而是元素的個數。
從而p + 0x1的值爲:0x100000 + sizeof(Test)*0x1,而sizeof(Test)大小爲20byte,
所以p + 0x1的值爲:0x100014
b: 這裏涉及強制轉換,將指針變量p保存的值強制轉換成無符號的長整型數,任何數值一旦被
強制轉換,其類型就改變了,從而這個表達式其實就是一個無符號的長整型數加上另外一個整數,
所以其值爲:0x100001
c: 這裏p被強制轉化成一個指向無符號整型的指針,所以其值爲:0x100000 + sizeof(unsigned int*) * 0x1 = 0x100004
我們再來看一個具體例子:
int main()
{
   int a[4] = {1,2,3,4};
   int *ptr1 = (int *)(&a + 1);
   int *ptr2 = (int *)((int)a + 1);
  
   printf("%x %x",ptr1[-1],*ptr2);
   return 0;
}
對於ptr1: 將&a + 1的值強制轉換成int *類型,賦值給int *類型的變量ptr1,那麼ptr1的指向如下圖所示:
ptr1[-1]被解析成*(ptr1 - 1),即ptr1往後退4個byte,從而其值爲0x4.
對於ptr2: 按照上述b中的解釋,(int)a是強制轉化,就是把一個地址強制轉化爲了一個int類型的整數,(int)a + 1
就是從a或者a[0]開始往後加1個字節,也就是(int)a + 1的值爲元素a[0]的第二個字節的地址(注意:a[0]佔4個字節),然後把
這個地址強制轉化成int *類型的值賦值給ptr2,也就是說*ptr2的值應該爲元素a[0]的第二個字節開始連續4個byte的內容,內存佈局如下圖所示:

關於強制轉換

i.按照大端模式存放:
a[0]                                a[1]
00000000 00000000 00000000 00000001 00000000 00000000 00000000 00000010
提取後爲:
高                                低
00000000 00000000 00000001 00000000
值爲0x100

ii.按照小端模式存放:
a[0]                                a[1]
00000001 00000000 00000000 00000000 00000010 00000000 00000000 00000000
提取後爲:
低                                高
00000000 00000000 00000000 00000010
值爲0x2000000
這裏一定注意大小端模式在計算機內的存儲數據的順序和模式。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章