你必須知道的指針基礎-3.指針的移動及指針的危險


一、指針的移動

1.1 指針的向前及向后移動

  指針每次加一就是指針向前移動指針類型對應的字節數。下面通過一個int指針來指向一個int數組,看看指針的加法運算到底是個什么鬼?

    int nums[]={33,55,77,88,99};
    int* ptr = nums;
    printf("%d\n",*ptr);
    ptr++; // ptr是int類型的指針,所以向后移動4個字節
    printf("%d\n",*ptr);
    ptr+=2; // 向后移動2*4 個字節
    printf("%d\n",*ptr);

  運行結果如下圖所示:

  可以看到,指針的加法就是向前移動指定類型字節數,在數組中就是指向下一個元素。

  下面再來看看與加法相反的減法,仍然以上面的代碼為例,新增一句:ptr--;

    int nums[]={33,55,77,88,99};
    int* ptr = nums;
    printf("%d\n",*ptr);
    ptr++; // ptr是int類型的指針,所以向后移動4個字節
    printf("%d\n",*ptr);
    ptr+=2; // 向后移動2*4 個字節
    printf("%d\n",*ptr);
    ptr--;
    printf("%d\n",*ptr);

  運行結果如下圖所示:

  可以看出,減法即代表向后移動指針類型對應的字節數

1.2 char類型指針的移動

  對於char類型的指針移動,實際就是指向下一個字符或上一個字符:

    char s1[]="hello edisonchou.cn";
    char* p=s1;
    p=p+2; // char類型占一個字節,因此這里向后移動2*1個字節
    printf("%s\n",s1);
    printf("%s\n",p);

  這里實現了一個類似於求子串的操作,運行結果如下圖所示:

1.3 同類型指針的相減

  同類型指針相減,得出的是相距的數據類型的長度。下面以兩個指向同一個int數組的int類型指針為例,驗證一下是否得到相距的數據類型的長度:

    int nums[]={33,44,55,66,77};
    int* iP1=nums;
    int* iP2=nums;
    iP2=iP2+3; // 同類型指針相減得出的是相距的數據類型的長度
    printf("The distance is %d\n",iP2-iP1);

  當iP2-iP3得到的是距離是3,這是因為iP2在進行減法操作之前已經向前移動了3個int類型的長度。

二、指針強大但又危險

2.1 從你家到他家

  剛剛了解了指針的移動的強大,現在我們來看看指針的強大所帶來的一些“危險”。例如下面一段代碼,我們定義了兩個int類型的整數。

    int i1=555;
    int i2=666;
    int* p=&i1;
    printf("%d,%d\n",&i1,&i2);
    p--;
    int i3=*p; //從p當前指向的內存中取出4個字節,解釋成i3
    printf("%d\n",i3);

  在指針p的定義中,我們指向的是i1。而當我們對p指針進行減法運算移動時,我們發現當前p指針指向的居然不是i1而是i2了。這也就說明,本來聲明指針時指向的是你家的地址,而當對指針進行運算操作后卻指向了隔壁老王家的地址,這是搞什么鬼!

  可以從運行結果圖看出,i1和i2的地址分別為2686740和2686736(是連續的地址),p指針最開始指向的是i1。而當p向后移動之后,此時已經指向了i2。因此,輸出的值為666。

2.2 內存訪問越界

  繼續上面的例子,我們此時再將p指針向后移動,看看此時p指針所指向的內容的值是多少?當我們再把p指針向后移動99999位時,其所指向的內容的值又是多少?

    int i1=555;
    int i2=666;
    int* p=&i1;
    printf("%d,%d\n",&i1,&i2);
    p--;
    int i3=*p; //從p當前指向的內存中取出4個字節,解釋成i3
    printf("%d\n",i3);

    p--;
    printf("%d\n",*p);

  當運行程序后,結果變為了下圖:

  那么,這個4200782地址是個什么鬼?它存放的又是什么內容?我們不得而知,這也是另一個程序里邊某個變量所存儲的位置,但現在在我們這個程序中居然通過指針訪問到了!這是個可怕的事情!想想,當A程序中的指針通過移動取得了B程序中的內存地址或數據內容,再對指針對其修改數據,這是一件不安全的事兒!想想一幫苦逼程序員辛辛苦苦加班加點做的游戲,輕而易舉地就被掛了外掛,本來需要用RMB才能買的積分或者道具讓外掛直接給改了,是不是覺得人生已經沒有意義啦?

  下面一段代碼則展示了,當指針移動的距離過大時,Windows系統會對此訪問限制,程序直接報錯。

    p-=99999; //這個內存地址可能是無法訪問的,又被稱為訪問越界
    //Windows對此做了訪問越界的限制
    printf("%d\n",*p);

  運行結果是,直接崩潰,彈出錯誤按鈕:

  錯誤框的出現,代表了指針使用不當的危害,會給客戶造成一定時間的延遲服務。因此,指針雖然很強大,但是也很危險!

參考資料

  如鵬網,《C語言也能干大事(第三版)》

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM