[英]What is the difference between derefencing and assigning the address of a variable to pointer variable in C?
看下面兩個代碼!
int main() {
int a = 12;
int *p;
*p = a;
}
和這個代碼,
int main() {
int a = 12;
int *p;
p = &a;
}
在第一段代碼中將指針解引用為 this *p = a
,在第二段代碼中,變量a
的地址被設置為指針變量。
我的問題是這兩段代碼有什么區別?
在你的第一段代碼中:
int main() {
int a = 12;
int *p;
*p = a;
}
你有未定義行為嚴重的情況,因為你正在試圖做的是價值分配a
給int
變量p
目前點。 但是, p
尚未分配“地址”,因此它將具有任意且無效的值! 某些編譯器可能會將p
初始化為零(或NULL
),但這仍然是無效地址(在大多數系統上)。
您的第二個代碼片段是“健全的”,但就目前而言,實際上並沒有實現任何目標:
int main() {
int a = 12;
int *p;
p = &a;
}
在這里,您正在為指針變量p
分配一個值(即地址); 在這種情況下, p
現在指向a
變量(即,它的值是地址a
)。
因此,如果您附加這樣的代碼(在第二個代碼段的末尾):
*p = 42;
然后打印出來的值a
,你會看到它的值已經從最初賦予改變12
至42
。
隨時要求進一步澄清和/或解釋。
聲明*p
和a
是在內存中保留一些空間,用於第一種情況下的指針,第二種情況下a
是什么(一個int
)。
在這兩種情況下,如果您不將任何內容放入其中,則不會初始化它們的值。 這並不意味着其中沒有任何內容,因為這是不可能的。 這意味着它們的值是不確定的,有點“隨機”; 加載程序只是在請求時將代碼/數據放入內存中,而p
占用的空間和a
占用的空間都是加載時內存的任何內容(也可能是編譯時,但無論如何,未定)。
所以,你需要做一個大的風險*p = a
在1日的情況下,既然你問了processeur采取字節“內部” a
並將它們存儲的地方p
點處。 可能在您的數據段的范圍內,在堆棧中,不會立即導致問題/崩潰的某個地方,但很有可能,這很可能不行!
這就是為什么說這個問題會導致“未定義行為”(UB)。
第一個不好:
int main() {
int a = 12;
int *p;
*p = a;
}
這意味着:將變量a
的值放入指針p
指向的位置。 但是p
點是什么? 可能什么都沒有(NULL)或任何隨機地址。 在最好的情況下,它可能會導致執行錯誤,如訪問沖突或分段錯誤。 在最壞的情況下,它可以覆蓋完全未知變量的任何現有值,從而導致很難調查的問題。
第二個沒問題。
int main() {
int a = 12;
int *p;
p = &a;
}
這意味着:獲取指向(現有)變量a
指針並將其分配給指針p
。 所以,這將正常工作。
當您初始化一個指針時,您可以使用 *p 訪問指向變量的指針值而不是指向變量的地址,但不可能影響這樣的值(使用 *p=a)。 因為你試圖影響一個沒有變量地址的值。
第二個代碼是正確使用 p = &a
在 C 中取消引用和將變量的地址分配給指針變量有什么區別?
后者是前者的前提。 它們是實現指針取消引用的好處的單獨步驟。
為了解釋它們之間的區別,我們必須分別看看這些家伙是什么:
首先我們需要看看引用是什么。 引用是對象的標識符。 我們可以說“變量a
代表12
的值”。 - 因此, a
是對12
值的引用。
對象的標識符是對存儲在其中的值的引用。
指針也是如此。 指針就像通常的對象一樣,它們在內部存儲一個值,因此它們引用其中存儲的值。
“取消引用”是當我們“禁用”與其中的常用值的這種連接並使用p
的標識符來訪問/引用與p
存儲的值不同的值時。
“解引用的指針”是指簡單地,可以使用指針來訪問存儲在另一個對象,FE的值12
在a
通過它自己的標識符而不是a
。
要取消引用指針, *
取消引用運算符需要位於指針變量之前,例如*p
。
我們正在實現“什么是取消引用指針?”中所述的事情,通過給指針一個另一個對象的地址作為它的值,就像我們給一個普通變量賦值一樣。
但與通常的對象初始化/賦值相反,為此我們需要使用&
符號運算符,在變量之前,指針應指向其值,指針之前的*
取消引用運算符必須省略,例如:
p = &a;
Therafter,指針“指向”到存儲所需值的地址。
首先要做的是聲明一個指針,例如:
int *p;
在這種情況下,我們聲明了一個p
的指針變量,它指向一個int
類型的對象。
第二步是使用int
類型對象的地址值初始化指針:
int a = 12;
p = &a; //Here we assign the address of `a` to p, not the value of 12.
注意:如果你想要一個對象的地址值,就像一個普通的變量,你需要在對象之前使用&
的一元運算符。
如果你已經完成了這些步驟,你最終能夠通過使用*
操作符,在指針對象之前訪問指針指向的對象的值:
*p = a;
我的問題是這兩段代碼有什么區別?
區別很簡單,第一段代碼:
int main() {
int a = 12;
int *p;
*p = a;
}
通過取消引用指針來尋址對象是無效的。 如果之前沒有進行過指針引用的引用,則不能為指針的解引用賦值。
因此,您的假設是:
在第一段代碼中,我將指針取消引用為 *p = a...
是不正確的。
在這種情況下,您根本無法使用*p = a
以正確的方式解除對指針的引用,因為指針p
沒有任何引用,您可以正確地解除對指針的引用。
實際上,您正在將帶有*p = a
語句的a
值分配到您記憶中的必殺技中。
通常,編譯器將永遠不會通過沒有錯誤傳遞此。
如果他這樣做了,而您以后想要使用該值,您認為您已經通過使用指針正確分配了該值,例如printf("%d",*p)
您應該得到Segmentation fault (core dumped)
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.