2015-04-02 117 views
9

我仍然想知道爲什麼在C中你不能簡單地使用普通變量來設置其他的東西。變量本身是指向數據的指針,不是嗎?那麼,爲什麼只要使用原始變量,指針指向變量中的數據呢?它是否訪問所述變量中的特定位(或字節,我猜)數據?爲什麼在C中使用指針?

我敢肯定,這是合乎邏輯的,但是我從來沒有充分把握的概念和讀碼看*pointers時總是會引發我。

+0

學習時,我發現更容易記住,無論指針看起來有多複雜,只是指向一個存儲地址的變量。所以'char *** p'是可怕的想法,但它最終只擁有一個內存地址。 – teppic 2015-04-02 23:04:21

+4

如果「原始變量」是10MB網絡緩衝區,該怎麼辦?你如何將它傳遞給函數,複製它?你會如何排隊到另一個線程,複製兩次? – 2015-04-02 23:23:54

+0

@MartinJames很好的提示。 – Gewure 2017-02-28 10:42:13

回答

13

變量本身是一個指向數據

不,事實並非如此。一個變量代表一個對象,一個左值左值的概念與指針的概念有根本的不同。你似乎混在一起了。

在C中,「重新綁定」一個左值使其「指向」內存中的不同位置是不可能的。在編譯時確定並固定左值和它們的存儲位置之間的綁定。它並不總是100%特定的(例如,局部變量的絕對位置在編譯時是未知的),但它足夠具體以使其在運行時不可用戶調整。

的指針的整個構思是,其值在運行時通常確定,並且可以製成指向在運行時不同的存儲位置。

7

不,變量不是指向數據的指針。如果用int x, y;聲明兩個整數,則無法使xy指向相同的東西;他們是分開的。

每當你讀或從變量寫,你的計算機有以某種方式確定您的計算機的內存變量的準確位置。您的計算機將查看您編寫的代碼並使用它來確定變量的位置。 指針可以表示在編譯代碼時位置未知的情況;只有在實際運行代碼時纔會計算確切的地址。

如果您不允許使用指針或數組,則您編寫的每行代碼都必須訪問編譯時已知的特定變量。您無法編寫一段從調用程序指定的內存中不同位置讀寫的代碼。

注意:您還可以使用數組與變量索引訪問變量,其位置在編譯時不知道,但是數組是指針大多隻是語法糖。您可以考慮指針操作方面的所有數組操作。數組並不像指針那樣靈活。

另一個警告:如螞蟻指出的,局部變量的位置通常在堆棧上是,因此它們是一種可變的,其中位置並不在編譯時已知的。但是棧函數存儲局部變量的唯一原因是你的編譯器實現了隱藏的指針叫做堆棧指針和/或幀指針,函數使用這些指針來找出哪部分內存存放它們的參數和局部變量。 指針非常有用,編譯器實際上在背後使用它們而不告訴你。

5

指針是有幫助的一個常見的地方是當你正在寫函數。函數的參數是「按值」,這意味着它們獲得傳入內容的副本,並且函數爲其參數中的一個賦值,而不會影響調用方。這意味着,你不能寫這樣一個「倍增」的功能:

void doubling(int x) 
{ 
    x = x * 2; 
} 

這是有道理的,因爲否則將程序做,如果你這樣調用加倍:

doubling(5); 

指針提供工具來解決這個問題,因爲他們讓你寫一個採取變量的地址,例如功能:

void doubling2(int *x) 
{ 
    (*x) = (*x) * 2; 
} 

上面的函數需要一個整數a的地址它的論點。函數體中的一行將這個地址解引用兩次:在等號的左邊,我們將存儲到該地址中,在右邊,我們從該地址獲得整數值,然後乘以2最終的結果是在該地址找到的值現在翻倍了。

順便說一句,當我們想要把這種新的功能,我們不能通在文字值(例如doubling2(5)),因爲它不能編譯,因爲我們沒有正確地給函數的地址。給它一個地址是這樣一種方法:

int a = 5; 
doubling2(&a); 

這樣做的最終結果將是我們的可變a將包含10

+0

我最喜歡這個答案。它的直接和簡單的例子是非常好的。 – Gewure 2017-02-28 10:53:48

3

另一個原因:C旨在建立操作系統和大量的處理硬件的低級代碼。每一個硬件都通過寄存器來公開其接口,並且在幾乎所有的體系結構中,寄存器都映射到CPU存儲空間,並且它們始終不在同一個地址中(多虧了跳線設置,即插即用,自動配置等等)

因此,OS編寫者在編寫驅動程序時,需要一種方法來處理似乎內存位置,只是它們不引用RAM單元。

通過允許OS編寫者指定他或她想要訪問的存儲位置,指針用於此目的。

相關問題