目錄
指標是一種資料型別
指標也是一種變數,占有記憶體空間,用來儲存記憶體位址
測試一下指標變數占用空間大小
*p的含義—操作記憶體
*p放在等號的左邊賦值(給記憶體賦值)
*p放在等號的右邊取值(從記憶體獲取值)
指標變數和它指向的記憶體塊是兩個不同的概念
指標是一種資料型別,是指它指向的記憶體空間的資料型別
總體**
變數是記憶體的編號,而變數本身也是占用記憶體空間的。如下面的三行**,a是乙個變數,p1也是乙個變數,他們都是變數,意思是他們都是要求編譯器給他們分配記憶體而已,只不過是資料型別不一樣,就是他們所要求的給它們分配的記憶體大小不一樣而已。哪怕是像第三行前面有一堆的「*」,p2還是個變數,和a和p1沒啥區別。
int a = 10;
char *p1 = 100; //分配4個位元組的記憶體
char ****p2 = 100;
printf("a:%d , p1:%d , p2: %d", sizeof(a), sizeof(p1), sizeof(p2));
輸出為:
說明,指標變數的大小為4個位元組。
在指標宣告時,*號表示所宣告的變數為指標;在指標使用時,*號表示 操作 指標所指向的記憶體空間中的值
*p相當於通過位址(p變數的值)找到一塊記憶體;然後操作記憶體
「*」就像一把鑰匙 通過乙個位址(&a),去間接的修改a變數所表示的記憶體空間的內容
void main81()
整個過程描述如下:變數a在棧區開闢了一塊記憶體空間,裡面存放數值10(這個數值10不是a開闢空間的大小,只是往裡面存的值,a開闢的空間大小僅為4個位元組,因為a是int型別的資料結構),變數p3也開闢一塊兒記憶體空間,裡面為0(null)。「&a」代表取出變數a的位址,賦給p3,那麼p3裡面的內容就不是null了,就是a的位址了,這裡假設為0xaa11。再接著,"*p3"中的「*」號就好比是乙個鑰匙,可以之間訪問到p3所包含的內容作為位址,對應的地方。即a的位址,那直接"*p3=20;"等同於間接修改了a的內容了。當然這一切,都得是"*p3"位於等號的左邊才可以。
同樣,接著剛才的程式寫,把「*p3」放在等號的右邊,讓其等於c。這就相當於,從「*p3」對應的記憶體中取值,放到變數c中。剛才已經說了,「*p3」對應的值是變數a的值,那麼這麼一搞,c中的值就和a中的值是一樣的了。
//*p放在=號左邊 寫記憶體
//*p放=號的右邊 讀記憶體
執行所看,c的確是20。
上面的三行**,只想表達乙個意思,就是不斷的給指標賦值,相當於改變指標方向。p4被賦值了兩次,相當於改變了兩次指標方向。 如圖所示:
需要牢記的是:
1) 給p賦值p=0x1111;只會改變指標變數值,不會改變所指的內容;p = p +1; p++皆同此理。
2) 給*p賦值*p='a';不會改變指標變數的值,只會改變所指的記憶體塊的值
3) =左邊*p 表示給記憶體賦值, =右邊*p表示取值含義不同,切記切記!
4) =左邊char *p
5)保證所指的記憶體塊能修改(如果想修改指標所指向的記憶體空間的值,要先保證這個值可以被修改,否則,一修改,肯定報錯 )
再舉個例子:
char *getstr81()
void main()
這個程式一執行,就會報錯,因為tmp="abcdefgf",相當於把資料寫入了常量區(全域性區)中,這個區域的資料被編譯器保護,不可被修改。而*(p+2) = 'r',強制的進行修改,就會報錯。這是乙個經常犯的錯誤!
ps:這裡我是有疑問的,在最開始的介紹「*p」在等號左邊的時候,有過說:「*」就像一把鑰匙 通過乙個位址(&a),去間接的修改a變數所表示的記憶體空間的內容,那放在此處,*(p+2)的用法,應該是去修改以p+2記憶體空間所存放的位址的對應的記憶體空間,而不是p裡面所對應的記憶體空間吧。
這個理解是錯誤的!!!!!我想了很久才想明白了。在之前record5中介紹全域性區的記憶體空間如何和棧區的變數建立關係的時候就已經說過。在全域性區里開乙個新的記憶體空間來存常量,把這個常量所存的位址傳給對應的變數所開的記憶體空間裡面去,作為其存的值。那麼按照這個思路看此例,tmp = "abcdefgf";,變數tmp中存的值並非是「abcdefgf」,而是「abcdefgf」存放在全域性區記憶體位置的首位址。那麼後面的,*(p+2),提取的也就是所存的首位址向後數第二個的位置的位址,即「c」,那麼*(p+2)='r',就是想把"c"給強制轉換成「r」,常量無法被修改,於是,報錯。
看個例子:
千萬不要被多個星給迷住了!
int getabc1(char *p1); int getabc1(char* p1);
int getabc2(char ** p2); int getabc2(char * *p2); int getabc2(char **p2);
int getabc3(char ***p3);
int getabc4(char (*p4)[30]); int getabc4(char (*p4) [30]);
int getabc5(char p5[10][30]); int getabc5(char p5[10][30]);
如何理解這些變數或者或是指標?如何明白每乙個代表的是什麼含義?
答案是,人怎麼理解無所謂,重要的是編譯器怎麼來理解。在編譯器看來,只要你前面加了乙個"*"號,那就把你這個變數當成乙個指標變數(形參),就給你固定開4個位元組的記憶體空間而已。
當針做函式引數,形參有多級指標的時候, 我們只需要站在編譯器的角度 ,只需要分配4個位元組的記憶體(32bit平台)
當我們使用記憶體的時候,我們才關心指標所指向的記憶體是一維的還是二維的
p++ == (unsigned char )p+sizeof(a);
指標的資料型別決定了指標的步長,這是指標的理論基礎。指標的步長,根據所指記憶體空間型別來定。
注意:
建立指標指向誰,就把誰的位址賦值給指標。圖和**和二為一。
不斷的給指標變數賦值,就是不斷的改變指標變數(和所指向記憶體空間沒有任何關係)。
dm08_指標鐵律1.c
#define _crt_secure_no_warnings
#include #include #include void main81()
printf("a:%d , p1:%d , p2: %d", sizeof(a), sizeof(p1), sizeof(p2));
printf("hello...\n");
system("pause");
return ;
}char *getstr81()
/*int getabc1(char *p1); int getabc1(char* p1);
int getabc2(char ** p2); int getabc2(char * *p2); int getabc2(char **p2);
int getabc3(char ***p3);
int getabc4(char (*p4)[30]); int getabc4(char (*p4) [30]);
int getabc5(char p5[10][30]); int getabc5(char p5[10][30]);
//指標做函式引數 形參有多級指標的時候,
//站在編譯器的角度 ,只需要分配4個位元組的記憶體(32bit平台)
//當我們使用記憶體的時候,我們才關心指標所指向的記憶體 是一維的還是二維的
*/void main()
24 指標的本質
變數代表一段儲存空間的別名,但並不是只能通過變數才能訪問一段記憶體了,指標也可以 1 號的意義 p i p i 為什麼指標的大小占用為4個位元組?因為如果系統是32位,位址定址範圍為4個位元組,所有的32位位址值都可以用4個位元組表示,所以32位系統指標的大小都為4個位元組 2 傳值呼叫與傳址呼叫 ...
26 指標的本質分析
程式中的變數是一段儲存空間的別名,本質上是一段儲存空間。問題 是不是只能通過變數使用儲存空間?include int main 總結 可以通過指標來使用儲存空間。在指標宣告時,號表示所宣告的變數為指標 在指標使用時,號表示取指標所指向的記憶體空間中的值。指標的特殊點 1.指標的本質是變數,但變數的值...
26 指標的本質分析
注 部落格中內容主要來自 狄泰軟體學院 部落格僅當私人筆記使用。測試環境 ubuntu 10.10 gcc版本 4.4.5 一 變數回顧 程式中的變數只是一段儲存空間的別名,那麼是不是必須通過這個別名才能使用這段儲存空間?二 思考 下面的程式輸出什麼?為什麼?int i 5 int p i prin...