2014-02-23 48 views
-2

在下面的代碼:指針操作,內存掃描

#include <stdio.h> 
int main(int argc,char** argv) 
{ 
    char *str = "Hello world"; 
    char *p = &argc+1; 
    printf("%i \n",(&argc+1));   
    printf("%i \n",*(&argc+1)); 
    printf("%i \n",&str);    
    printf("%i \n",*str); 
    printf("%i \n",p);     
    printf("%i \n",*p); 
    return 0; 
} 

輸出是:

-541685632 
4196028 
-541685632 
72 
-541685632 
-68 

我的問題是,因爲它們都指向同一個地址怎麼來的,他們都指向了什麼以不同的價值;

+0

注意:您應該使用'%p'來顯示指針值。 –

+1

更重要的是,'(&argc + 1)'不是獲取'argv'的有效方法。你的程序調用未定義的行爲。如果您想了解發生的事情,請查看生成的彙編器。但是這通常不會告訴你C的行爲。 –

+0

其實對我來說'(&argc + 1)'導致崩潰:-O –

回答

0

&argc+1指向可能未分配給程序的內存。這是未定義的行爲,所以如果你的觀察與你的期望不同,你不應該感到驚訝。

2

當然,這一切都是不確定的行爲,但鑑於&argc+1恰好是&str您的具體實現,這裏就是爲什麼你讓你上執行看到的行爲:

首先,讓我們擺脫&argc+1,只是使用&str代替:

#include <stdio.h> 
int main(int argc,char** argv) 
{ 
    char *str = "Hello world"; 
    char *p = &str; 
    printf("%i \n", &str); 
    printf("%i \n",*(&str)); // (1) 
    printf("%i \n", &str); 
    printf("%i \n", *str); // (2) 
    printf("%i \n", p); 
    printf("%i \n",*p); // (3) 
    return 0; 
} 

在(1)你打印*(&str),這當然是一樣的str。這將打印存儲在變量str中的內存地址。 (2)您正在打印*str。因此,您將存儲在str中的指針取消引用。 *str的值將是'H'(又名72),因爲那是生活在str指向的地址處的字符。

On(3)您正在打印p指向的值。 p指向str,因此您可能預計str的值將如同(1)上的那樣打印。然而,你宣稱p是一個char指針,因此解引用它只能讀取一個字符。所以你得到的僅僅是str的值的第一個字節。

0

所不同的是在類型取消引用指針的:

  • (&argc+1)是一個指向int,解除引用將interprete四個字節爲一個整數。

  • &str是指向指向char的指針,取消引用它會將四/八個字節解釋爲指向字符的一個指針。但是,您的代碼會將其解除引用兩次,因此當您打印*str時,會在內存中的其他位置打印一個字節。

  • p是指向char的指針,取消引用它將只解釋一個字節,就像一個字節。

除此之外,當然,提領(&argc+1)沒有C標準的祝福,它可以讓編譯器生成代碼,在您做反引用點做不惜一切代價。這絕對包括打開一個互聯網連接,默默下載並安裝一個漂亮的小程序來記錄你的每一個擊鍵,並直接發送給N​​SA或其他人...所以,儘量避免調用未定義的行爲。

0

首先,這些並不都指向相同的地址...您認爲str的地址與&argc+1的地址相同的原因是什麼?我不認爲這兩個在ANY C編譯器上都是一樣的!但是這樣的事情是非常依賴於編譯器和平臺的,所以嘗試以這種方式訪問​​內存是一個糟糕的想法,並且非常不便攜。

但是,暫時擱置一會兒,即使它們的DID指向相同的地址,您在每種情況下都以不同的方式使用該地址......在(&argc+1)的情況下,您正在打印指針的值(作爲整數)。在*(argc+1)的情況下,您正在打印指向第一個指針的int。在&str的情況下,您正在打印ADDRESS-OF str(與str的內容無關)。用*str,您正在打印由str指向的char。與p一樣,您正在打印指針的值,與第一種情況(&argc+1)一樣。最後,使用*p您正在打印先前指針指向的char

此外,您正在使用%i格式來打印所有這些值,儘管打印的值的實際數據類型各不相同...有些是指針(通常是32位,在大多數實現中),有些是char是8位的。 printf如何處理與相應的格式字符串不匹配的數據值因實現而異,這是不好的做法!當我嘗試在Linux/Fedora下使用gcc 4.8.1進行編譯時,它會得到多個編譯時錯誤。

總而言之,很多醜陋的東西都在這裏!