簡體   English   中英

我不懂C ++指針算法

[英]I don't understand C++ pointer arithmetic

我有以下程序,它定義了2個整數和一個指向整數的指針。

#include <stdio.h>

int main() {

    int bla=999;
    int a=42;
    int* pa=&a;

    printf("%d \n", *pa);
    printf("%d \n", pa);

    pa++;
    //*pa=666; //runs (no error), but the console is showing nothing at all

    printf("%d \n", *pa);
    printf("%d \n", pa);

    pa++;
    //*pa=666; //runs and changes the value of *pa to 666;

    printf("%d \n", *pa);
    printf("%d \n", pa);

}

輸出是:

42

2686740

2686744

2686744 //這個值很奇怪,我想

999

2686748

地址對我來說很有意義,但第四個值很奇怪,因為它正是int的地址。 有人可以解釋一下這種行為嗎?

當我評論* pa = 666(第一個外觀)時,控制台什么也沒顯示,所以這里有一些錯誤,但是編譯器沒有顯示錯誤。 也許這是因為我的系統上的int的大小,我有一個64位的Windows-os,所以也許int是64位而不是32? 並且因為第二次增量后* pa值是999而不是第一次?

我相信,有很多C程序員可以解釋發生了什么:)

int* pa=&a;

pa是指向整數的指針,並且定義了訪問*pa

一旦遞增指針,指針指向某個內存(在p之后),這個內存未由您分配或您不知道,因此取消引用它會導致未定義的行為。

pa++;

*pa是UB

編輯:

使用正確的格式說明符打印@haccks指出的指針值%p

您使用錯誤的格式說明符來打印地址。 這將調用未定義的行為,並且一旦調用UB,所有投注都將關閉。 請改用%p

printf("%p \n", (void *)pa);  

另一個問題是執行pa++; ,您正在訪問未分配的內存和UB的另一個原因。

輸出並不奇怪,可以預料到:你在main()有三個變量,所有這些變量都存儲在堆棧中,並且它們一個接一個地發生。 其中一個變量是指針本身。 因此,當您取消引用第三行中的指針時,您將獲得指針本身的當前值。

然而,這個輸出是不可預測的,它是未定義的行為:您只能使用指針算法來訪問單個內存對象中的數據,在您的情況下,內存對象只是一個int 因此,在第一個pa++之后訪問*pa是非法的,並且允許程序從該點開始執行任何操作。

更具體地說,不能保證哪個其他變量遵循某個變量,它們遵循哪個順序,或者是否存在可訪問的存儲器。 甚至在第一個pa++之后讀取*pa也會導致程序崩潰。 正如您所見,在許多情況下(這很容易調試)您不會遇到崩潰,但代碼仍然深受打擊。

你並不比你的編譯器更聰明。

正如另一個答案所說,你所做的是未定義的行為。 對於pa你只是無意義,它與任何可定義的目標的可推理算法都不對應:它是無意義的。

但是我會向你提出一個可能出現的情況。 雖然大部分都可能是錯誤的,因為編譯器會進行優化。

int bla=999;
int a=42;
int* pa=&a;

這些變量在堆棧上分配。

當寫pa = &a你說“我希望指針pa等於a的地址”。

編譯器可能已經在訂單或聲明中分配了內存,這可能會給出類似的結果:

  • bla地址為0x00008880
  • a地址為0x00008884
  • pa地址為0x00008888

當你做pa++你會說:將我的int指針移動到內存中int的下一個位置。 由於int是32位,你正在做pa = pa + 4bytes pa = 0x00008888pa = 0x00008888

請注意, 偶然! ,你可能指向pa指針的地址。 所以現在指針pa包含它自己的地址......這非常深奧,可以稱為ouroboros

然后你又要問pa++ ...所以pa = pa + 4 bytespa = 0x0000888c

所以現在你可能正在訪問一個未知的內存區域。 它可能是訪問沖突。 如果你想讀或寫,這是未定義的行為。

當您第一次分配指針時,它指向2686740 指針是一個整數指針,整數使用4個字節(通常,在你的機器上它使用4個字節)。 這意味着pa++將把值增加到4,即2686744 再做一次導致2686748

如果您要查看生成的匯編代碼,則可以切換局部變量的順序。 代碼運行時,順序是apabla 由於您沒有明確控制此排序,因此打印輸出被視為未定義

在你第一次使用pa++ ,指針指向自身,這就是為什么你得到了“奇怪的價值”

正如許多其他答案所提到的,這不是指針的好用,應該避免。 在這種情況下,您無法控制指針指向的內容。 更好地使用指針算法將指向數組的開頭,然后執行pa++指向數組中的下一個元素。 您可能遇到的唯一問題是遞增超過數組的最后一個元素

你們是不是要增加的值a通過指針*pa

如果是這樣,請執行: (*pa)++ 括號是至關重要的,因為它們意味着“獲取指針的值”,然后使用該地址遞增引用的任何內容。

這與*pa++完全不同,它只返回*pa指向的值,然后遞增指針 (而不是它引用的東西)。

C語法的一小陷阱。 K&R有幾頁專門討論這個問題,我建議你嘗試一些例子。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM