我很難理解指標以及它們如何/何時失敗。所以我做了一個小程式,它創建一個指標,為其分配一個值,然后列印該值。使用 gcc 和 clang 都可以正常編譯,并且在使用 -Wall 開關時不會給出任何警告。為什么它會出現段錯誤,為什么當我首先為指標分配不同的值時它不會出現段錯誤?我以為我已經初始化了指向某個地方的指標。當我只宣告沒有初始化的指標時,我理所當然地得到了編譯器警告。但是,在這里我沒有收到編譯器警告,但它仍然存在段錯誤。
#include<iostream>
int main(){
int *b = (int*) 12; //pointer gets initialized, so it points to somewhere
//int a = 13; //works fine when uncommenting this and the next line
//b = &a;
*b = 11;
std::cout << "*b = " << *b << "\n";
return 0;
}
uj5u.com熱心網友回復:
指標是保存記憶體地址的變數。
您“可以”在指標中有任何記憶體地址,但嘗試從允許讀取應用程式的記憶體空間之外的記憶體空間讀取,將觸發作業系統以段錯誤錯誤殺死您的應用程式。
如果你允許我做個比喻:
您可以在紙上寫下您所在國家/地區的任何人的地址。但如果你試圖未經許可進入那所房子,你很可能會被警察攔下。
回到代碼:
int *b = (int*) 123; // ok, you can save what you want.
std::cout << *b << std::endl; // SEGFAULT: you are not allowed to read at 123.
當您取消注釋這兩行代碼時:
int a = 13;
b = &a;
基本上,b不再指向那個禁止123地址,而是指向a. a在你自己的代碼中,它的記憶體對你沒有禁止,所以*b在這之后訪問是允許的。
C 不禁止讀取任何硬編碼地址(實際上它在某些情況下很有用),但您的作業系統可能不允許您弄亂該記憶體。
另一方面,編譯器能夠在沒有初始化的情況下檢測到正在使用的變數,并且可以警告這種情況。這與原始指標無關。
uj5u.com熱心網友回復:
指標是存盤地址的變數。
int *b = (int*) 12;
這宣告b為指向型別值的指標int,并使用地址對其進行初始化12。你知道地址是什么12嗎?不,你沒有。因此,您不應使用該地址。
*b = 11;
11這將在指標指向的地址存盤一個整數b。但是,由于指標b指向 address 12,因此整數11會覆寫該地址處的某些內容(我們甚至不知道它會覆寫什么,因為我們不知道從什么開始)。這可能會破壞堆或堆疊或程式的代碼,或者只是導致訪問沖突,任何事情都可能發生。
但如果你先這樣做:
b = &a;
然后指標b現在指向a存盤變數的地址。因此,隨后11在該地址寫入只會覆寫a的值(從 13 到 11),這是一個完全有效的操作,沒有問題。
我只需要它指向某個可以容納
int
確實如此,但這還不夠。該位置不僅應該能夠保存一個int,而且該位置還必須可供您的程式存盤這樣一個int. 這意味著該位置需要是現有物件的位置(例如,現有型別的變數int)或新分配的能夠保存int. 例如:
b = new int;
這將動態分配存盤 a 所需的記憶體int,并將新分配的記憶體的地址分配給指標b。
請記住,在使用完這種動態分配的記憶體后,您應該釋放它:
delete b;
否則,將會出現記憶體泄漏(至少在整個行程退出之前)。
如今,在現代 C 中,很少需要使用原始指標來手動管理動態記憶體分配/釋放。為此,您將使用標準容器和/或智能指標。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/444618.html
