指針:
一、聲明 一個 int 類型的 指針 然後 賦值。
二、聲明中直接賦值。
三、空指針
四、懸空指針 野指針:
懸空指針本質上就是 聲明了一個 指針類型的變量【如:int *p】,並且沒有賦值。在沒有賦初值的情況下,利用這個指針進行修改【如:*p=100】。就相當於這個指針指向了一個未知的地址。並且還做了修改。那如果這個地址是其他進程。還做了修改,就會造成系統的不穩定。因為這種不可靠的修改行為極其可怕,就好像呂伯奢開放了自己家給曹操,曹操進來以後胡亂的修改呂伯奢家人的數據,把是否存活全都置成了false.在dos版本的操作系統下,這種修改行為還是可以的。但是隨著後來越來越多的黑客想要修改操作系統的數據,就相當於我操作系統很大度,開放了我自己給你,你運行了一些東西,讓我這個操作系統土崩瓦解了。所以後來的操作系統做成了如下圖的樣子:
也就是隨著後來越來越多的這種可怕行徑,導致後來的法律發現如果你越界訪問的話,我們就認定你是非法入室罪名。就是有一個進程不斷地檢測,如果 有用戶進程非法訪問,就立刻把這個進程從內存中清楚,以保護操作系統的穩定。所以我們現在 是可以放心做這種懸空指針的案例演示的,不過就是 我們的進程遇到了問題,被迫中止而已。這是可以接受的。
五、指針的兼容問題
以下代碼:
#include <iostream> void function1(void); void function2(void); void function3(void); void function4(void); void function5(void); int main() { function5(); return 0; } /** 聲明 一個 int 類型的 指針 然後 賦值。 */ void function1(void){ int i= 10; printf("修改前i的值為:%d\n",i); int *p;//定義一個 執行int 類型的指針 變量名為p. p = &i;//取i的地址 賦給 p。 *p = 100;//*p表示:訪問p中的內容,根據int 這個類型,來提取這個元素。 //又因為剛剛給這個裡面賦了i這個值 ,所以*p 相當於i。那麼i=100. //所以 *p = 100 本質上是一個賦值語句,將i的值改成了100. printf("修改後i的值為:%d\n",i); } /** 聲明中直接賦值。 */ void function2(void){ int i =10; int *p = &i; printf("i的值為:%d\n",*p); } /** 空指針 */ void function3(void){ //int b = NULL; //printf("b的值為:%d\n",b); int *p = NULL;//這就是傳說中的空指針,在java中報了錯比較常見這個東西的, //就是因為在創建對象的時候,沒有給定一個初值,導致 報了那樣一個異常 printf("指針p的值為:%d,%p,%x",p,p,p); } /** 懸空指針,野指針 :其實 跟function1()的內容有相像的地方,就是聲明一個指針類型的變量,但是不賦值。 這個 編譯是可以通過的,但是運行的時候會報錯。在visual studio c++ 裡面編譯通不過。 這是因為。誰也不知道 到底讓p指向了一個什麼樣的內存單元。並且在不知情的情況下還給 它賦了100這個值, 那這樣就會極其不安全。 */ void function4(void){ int *p; *p = 100; printf("懸空指針指向的地址的值是:%d\n",*p); } /** 指針的兼容問題 */ void function5(void){ //前面在第一個案例的時候有特意提到聲明了一個 int類型的指針變量,是因為除此之外還有各種類型的指針變量。 //比如: char *pc; int array[10]; int *p =array;//這個我現在有點兒蒙。。。 double *pd; //也就是我們說的,先去找到那個對應的元素然後按照 char 類型取pc裡面的內容 //按照double類型,取pd裡面的值 //所以對於指針來說 他們的大小都一樣: printf("指針變量pc的大小:%d\n指針變量p的大小%d\n指針變量pd的大小%d\n",sizeof(pc),sizeof(p),sizeof(pd)); //【查看運行結果圖】,會發現在這台機器裡面,所有的指針變量都是8,說明這是一個64位的操作系統。 //如果這些數值都是4說明這是一個32位的操作系統。所以指針變量這個值的大小是操作系統相關的。 //所以,在取值的時候需要為這個被指向的對象指明一個類型,方便在取的時候,按照合理的類型把這個元素提取出來。 // 為了繼續進行先把這裡注釋掉,這裡很關鍵!一定要動手嘗試 //所以 如果是 int *p1; char c; //p1=&c; //就會報一個這樣的錯誤: cannot convert 'char*' to 'int*' in assignment int *p2; unsigned int i1; //p1=&i1; //這個編譯還是很嚴格的,就是不行。在vs裡面這是被允許的。 //[Error] invalid conversion from 'unsigned int*' to 'int*' [-fpermissive] //但是 如果聲明一個 指向空類型的 指針 在進行指向是被允許的。 void *pv; pv=&c; pv=&i1; //這樣就是編譯通過的。 //p1 = pv; //[Error] invalid conversion from 'unsigned int*' to 'int*' [-fpermissive] }
上面是 main.cpp 的情況
下面是 main.c的情況:
#include <iostream> int main() { int *p; unsigned int i; //p=&i; //[Error] invalid conversion from 'unsigned int*' to 'int*' [-fpermissive] int ii; p=ⅈ void *p1; p1 = p; char *pc; //pc = p1; //[Error] invalid conversion from 'void*' to 'char*' [-fpermissive] return 0; }