main()
{
int i;
int *p = &i;
printf("%d",sizeof(p));
}
我32位CPU,
在VC測試: 4
在TC測試: 2
請問,指針變量存儲單元的大小與什么有關?
指針大小和當前系統的地址總線位數一樣,TC運行在16位模擬器中,所以指針大小是16位即2個字節,vc就是32位的,int類型的大小也和這個一樣是變的,其它類型的大小不會變的
TC和VC所支持的語言標準不同,跟16位和32位編程無關。
TC支持純C語言,純C語言里的6種int型數據中只有long和unsigned
long型長度是4字節,另外4種長度是2字節,而VC里支持的C語言全部6種int型數據長度全部是4字節。我們知道,指針的長度和其相應的數據類型長
度相等,所以int型指針在TC里是2字節,在VC里是4字節。
指針的大小是問:一個指針變量占用多少內存空間?
分析:既然指針只是要存儲另一個變量的地址,。注意,是存放一變量的地址,而不是存放一個變量本身,所以,不管指針指向什么類型的變量,它的大小總是固定的:只要能放得下一個地址就行!(這是一間只有煙盒大小的“房間”,因為它只需要入一張與著地址的紙條)。
存放一個地址需要幾個字節?答案是和一個 int 類型的大小相同:4字節。
所以,若有:
int* pInt;
char* pChar;
bool* pBool;
float* pFloat;
double* pDouble;
則:sizeof(pInt)、sizeof(pChar)、sizeof(pBool)、sizeof(pFloat)、sizeof(pDouble)的值全部為:4。
(你敢拆電腦嗎?拆開電腦,認得硬盤數據線嗎?仔細數數那扁寬的數據線由幾條細線組成?答案:32條,正是 4 * 8)。
指向數組的指針
現在,來說說指針指向一個數組的情況。
int arr[]
= {1,2,3,4,5}; //一個數組
int* parr; //一個指針。
parr = arr; //沒有‘&’?對啊,對數組就是不用取址符。
cout << *parr << endl;?
//輸出 *parr
先猜想一下,輸出結果是什么?
最“直覺”的想法是:parr
指向一個數組,那么輸出時,自然是輸出數組中的所有元素了。所以答案應該是:“12345”了?
不過,我想,學過前面的數組,我們就能知道這種想法錯誤。
正確答案是輸出數組中的第一個元素: 1 。
接下來,如果是這樣輸出呢?
parr =
arr;
cout << parr << endl;
答案是輸出了arr的地址。就等同于輸出
arr 。
cout << arr << endl; 的作用
在這里,難點是要記住,數組變量本身就是地址。所以有:
1、想讓指針變量存儲一個數組的地址(想讓指針變量指向一個數組)時,不用取址符。
2、解析一個指向數組的指針,得到的是數組的第一個元素
偏移指針
int* parr2;
parr2 = parr + 1;
加1后,指針指向了下一個元素。由于這是一個 int
類型的數組,每個元素的大小是4個字節。所以第二個元素的地址是10000014。
重點 &
易錯點:對指針 進行加1操作,得到的是下一個元素的地址,而不是原有地址值直接加1。
知到了如何“加”,也就知道了如何“減”。減以后,得到的是上一個元素的大小。
所以,一個類型為 T 的指針的移動,以
sizeof(T) 為移動單位。
所以,一個類型為 T 的指針的移動,以
sizeof(T) 為移動單位。
比如:
int* pInt; 移動單位為
sizeof(int) 。即:4。而 char* pChar; 移動單位為
sizeof(char)。即1。
指針的最小移動單位
int arr[6] = {101,102,103,104,105,106};
int* pI = arr;
cout << "pI
是一個指向整型數組的指針,移動單位:4字節" << endl;
for (int i = 0; i < 6; i++)
??
cout << "pI + " << i << " ----> " << pI + i << ", *(pI + i) = "? << *(pI
+ i) << endl;??
cout <<
"------------------------------------" << endl;
//接下
來是一個指向char類型數組的指針:
char str[4] = {'a','b','c','d'}
char*? pC = str;
cout << "pC
是一個指向字符數組的指針,移動單位:1字節" << endl;
for (int
i=0; i < 4; i++)
???
cout << "pC + " << i << " ----> " <<
(int)(pC + i) << ", *(pC + i) = "? << *(pC
+ i) << endl;??
system("PAUSE");
輸出結果:

(指針的最小移動單位)
每一行中,程序先輸出指針加上偏移量以后的值(地址),比如:1245024、1245028;然后輸出偏移后指針指向的值,比如101,102。
查看移動前后指針存儲的地址,我們就可以計算出移動單位。1245028 - 1245024 = 4 (byte)。
* (地址解析符)與 ++ 的優先級
指針的前置++與后置++的區別
//代碼片段一:
int arr[] =
{1,2,3,4,5,6,7,8,9,10};
int* parr1 = arr;
int A = *parr1++;
int B =
*parr1;
cout << "A = " << A << endl;
cout << "B = " << B << endl;
輸出結果:
A
= 1;
B = 2;
代碼片段二:
int arr[] = {1,2,3,4,5,6,7,8,9,10};
int* parr1 = arr;
int A
= *++parr1;
int B = *parr1;
cout << "A = " << A << endl;
cout << "B = " << B << endl;
輸出結果:
A
= 2;
B
= 2;
19.8.7* (地址解析符)與 ++ 的優先級
從上例中我們可以看到。當 * (作為地址解析符)和 ++ 同時作用在指針時,不管是前置還是++,都要比*有更高的優先級。比如代碼中的:
int A = *parr++;
我們來一個反證:假設*的優先級比++高,那么,應先計算:
*parr 結果為:
1 (第一個元素)
然后計算? 1++
,結果為:2。
但實驗發現結果為 1,這個1 又是如何來的呢?有點復雜。
首先,++優先計算,所以應先計算:parr++
。
結果是parr指向了下一個元素:2。因為這是后置++,所以,它必須返回自己計算之前的值;所以,在改變parr之前,編譯程序會生成一個臨時變量,計算原先parr的值。我們假設為
old_parr 。下面是第二步操作:
A = *old_parr。
由于
old_parr 是 parr 原來的值,指向第一個元素,所以
A 得到值: 1 。
可見,后置 ++ 或 后置--
操作,需要系統生成一個臨時變量。
如果這個變量占用的內存空間很小(比如指針類型總是只有4字節),則該操作帶來的,對程序速度的負面影響可以不計,如果變量很大,并且多次操作。則應在可能的情況下,盡量使用前置++或前置--操作。
你自然會問,前置++就不會產生臨時變量嗎?我們來試試。
int A = *++parr;
同樣,++優先級大于*,所以先計算:++parr。
結果parr
指向下一個元素。因為這是前置++,所以,它只需要返回的,正是自己計算之后的值。下一步是:
A =
*parr;
由于 parr 此時已完成++操作,指向下一個元素。所以 A
得到值: 2。
19.8.8上機實驗六:指針的 ++與--操作
int arr [] = {1,2,3,4,5};
int* parr = arr;
//前進
++:
for (int i=0; i < 5; i++) //如果為了優化,你可以寫成:
++i :)
{
??
cout << *parr << endl;
?? parr++;??
//如果為了優化,你可以寫成:++parr :D
?
?? /*
???? 上面兩句你還可以寫成一句:?
???? cout << *parr++ <<
endl;? //這里,你可不能為了優化寫成: *++parr.
? */
}
//后退 --:
for (int i=0; i < 5;
i++)
{
??
parr--;
?? cout << *parr << endl;
}
輸出結果:

(指針的++與--)