[英]clarification about C pointers
在以下示例中:
int *i;
*i=1;
它會產生一個掛起的程序,因為我知道我將一個值直接放入內存位置。
我的問題是為什么要執行以下操作:
int *i=1;
只產生與整數轉換有關的警告,而不會掛起程序?
為什么該指令不產生錯誤也沒有警告?
char *s="acd";
如果我正在使用類似於之前的示例
謝謝
讓我們分別討論這三種情況:
int *i;
*i=1;
第一行為指針分配內存,但不初始化它,使i保留隨機垃圾值。 第二行嘗試寫入由隨機垃圾說明的內存地址,從而在運行時導致未定義的行為。
int *i=1;
這為指針分配內存並為其分配值1(即內存地址0x1
)。 由於這會隱式地將整數值1強制轉換為指針,因此您會收到警告,因為極少初始化指向非空內存地址的指針。
順便說一句,如果您要執行以下操作:
int *i=1;
*i=1;
它將嘗試將值1寫入內存地址0x1
,從而導致與第一種情況相同的未定義行為。
char *s="acd";
這會在堆棧上創建一個以null終止的字符串,並指向它。 字符串文字是分配給char *的自然事物,因此沒有警告。
您的第一種情況是您嘗試寫入內存的唯一情況:
int *i; // i is a pointer but it's value is undefined
*i = 1; // Whoops, you just wrote to a random memory location.
int *i=1; // i is an invalid pointer (address 1), but you aren't writing to it
char *s="acd"; // s points to the string literal "acd" - again: no write.
int *i = 1;
等效於:
int *i;
i = 1;
出於同樣的原因:
char *s = "acd";
...相當於:
char *s;
s = "acd";
類型定義中星號的出現是表示i
和s
是指針的表示法。 這與您看到類型定義之外使用星號(表示取消引用)不同。
因此,在這些情況下,您只是在分配指針值本身,而不是對其進行解引用並寫入其指向的內存。 指針本身的內存在堆棧上分配,因此被占用。 當您取消引用並在未正確初始化時嘗試對其進行寫操作時,會出現危險。
請注意,在字符串的情況下,您可以取消引用它。 當編譯器看到字符串文字時,隱式地預留了acd\\0
四個內存字符,然后將文字求值到該內存的地址。 所以你s
指針是好的。 您的i
指針是一個任意值,在大多數系統上很可能無法讀取。
int *i;
聲明一個指針。 如果在函數中完成,則這是一個自動變量,並且不會初始化 。 然后,當您嘗試
*i = 1;
您訪問由分配給名稱i
的內存位置中的值所給定的某些內存。 您可能沒有訪問該內存的權限,因此程序崩潰。
當你寫
int *i = 1;
您聲明了指針並將其初始化為指向內存位置1。請注意,您沒有嘗試將任何內容寫入內存位置1,只需將i
指向它即可。 如果您確實嘗試對其進行寫操作,則會再次出現段錯誤。
您的最后一種情況聲明了一個字符指針,該字符指針指向字符串文字(因為"string"
值等於該文字存儲的地址),該地址通常存儲在您有權讀取但不能寫入的內存的特殊部分中。
對於第一部分,聲明:
int *i=1;
實際上與這樣做相同:
int *i;
i=1;
也就是說,指針i被聲明為在內存位置1(如果您具有32位地址空間,則為0x00000001)。 警告僅是因為您要將整數轉換為地址。
對於第二部分,這是聲明字符串的正確語法。 這就是為什么它不會觸發錯誤的原因。
在第一個例子中
int *i;
*i = 1;
您聲明一個指針並使其未初始化。 這是未初始化的,意味着它基本上具有隨機值,因此指針指向隨機存儲器位置。 然后,您嘗試將該位置的內存設置為一個值,這可能會使程序崩潰。 使用未初始化的指針是未定義的行為 。
在第二個示例中,您實際上是初始化了指針。 您沒有在i
指向的位置分配值,而是實際上使i
指向內存地址1
。
第三個示例只是第二個示例的變體,您在其中告訴指針s
指向存儲文字字符串"acd"
的內存。
在第一個示例中:
int *i;
*i=1;
您正在將1分配給i所指向的位置,該位置尚未初始化,因此很有可能寫入無效的位置。
在第二個示例中:
int *i = 1;
您正在將值1分配給指針值i-就是說我指向內存地址1。這等效於:
int *i;
i = 1;
發生警告是因為i的類型為int*
且類型為int
。
在最后一個示例中:
char *s="acd";
您正在分配s以指向字符串文字。 字符串文字存儲在程序的靜態內存中,因此在運行時會將其替換為有效地址。 攪動文字的類型是char*
,它與s
相同,因此沒有警告。
int *i;
聲明變量i
為一個指向int
的指針
*i = 1;
嘗試將整數1存儲在i
處存儲的任何地址。 在將任何內容存儲到i
之前執行此命令時,這應該是未定義的行為。 這可能是因為i
包含了一些隨機值,並且你因此嘗試存儲1在一個隨機地址。
int *i = 1;
將變量i
聲明為一個指向int
的指針,並嘗試將該指針初始化為1。由於1是一個整數,而不是整數的地址,因此會出現警告。
按照定義,像"acd"
這樣的字符串文字是一個以NULL
結尾的char
數組,其中包含字符串中的字符。 賦值時,此數組衰減為一個指向char
的指針,並且在將其分配給char *
時沒有問題。 不過,我認為您不應該修改該數組的元素,因此最好將其分配給const char *
,gcc可能會很樂意警告您。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.