簡體   English   中英

關於C指針的說明

[英]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";

類型定義中星號的出現是表示is是指針的表示法。 這與您看到類型定義之外使用星號(表示取消引用)不同。

因此,在這些情況下,您只是在分配指針值本身,而不是對其進行解引用並寫入其指向的內存。 指針本身的內存在堆棧上分配,因此被占用。 當您取消引用並在未正確初始化時嘗試對其進行寫操作時,會出現危險。

請注意,在字符串的情況下,您可以取消引用它。 當編譯器看到字符串文字時,隱式地預留了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.

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