內存和地址
計算機的內存由數以億萬的位(bit)組成,每個位可以容納值0和1。
但是,由於一個位能表示的值的範圍太有限了,所以單獨的位的用處不大!
通常將許多位合成一組作爲一個單位,這樣就可以存儲範圍較大的值。
其中每一個單位稱爲一個字節(byte),每個字節都包含了存儲一個字節所需要的位數。
通常,在大部分機器上,每個字節包含8個位,可以存儲無符號值0到255,或有符號值-128到127。
每個字節通過地址來標識。
爲了存儲更大的值,我們把兩個或更多的字節合在一起作爲一個更大的內存單位。
這個單位在許多機器上被稱爲字。
通常情況下,一個字由2個或4個字節組成。
如果一個字包含4個字節,那麼每個字可以容納的無符號整數範圍是從0到4294967295,可以容納的有符號範圍是從-2147483648到2147483647。
注意,儘管一個字包含了4個字節,它仍然只有一個地址。
地址與內容
由上可知:
- 內存中的每個位置都由一個獨一無二的地址標識。
- 內存中的每個位置都包含一個值。
如圖所示,5個數都位於自己所屬的字中。
顯而易見,我們可以通過其地址取得這個值。
但是這種方法實在是太麻瓜了。
所以C提供了一種特性——通過名字而不是地址來訪問內存的位置。當然,這些名字就是我們所稱的變量。
指針變量的內容
現在我們來看看存儲於這些位置的值。
int a = 112;
int b = -1;
float c = 3.14;
int *d = &a;
int *e = &c;
看看變量d和e的聲明。
它們都被聲明爲指針,並用其他變量的地址予以初始化。
指針的初始化時用&操作符來完成的,它用於產生操作數的內存地址。
間接訪問操作符*
區分指針變量的地址和它的內容是非常重要的。
通過一個指針訪問它所指向的地址的過程稱爲間接訪問或解引用指針。
這個用於執行間接訪問的操作符是單目操作符*。
表達式 | 值 | 類型 |
---|---|---|
a | 112 | int |
b | -1 | int |
c | 3.14 | float |
d | 100 | int * |
e | 108 | int * |
*d | 112 | int |
*e | 3.14 | float |
未初始化指針
int *a;
...
*a = 12;
我們本意是:聲明創建一個名叫a的指針變量,通過賦值語句把12存儲在a所指向的內存位置。
但是問題在於:我們聲明瞭這個變量,但從未對它進行初始化,所以我們沒有辦法預測12這個值將存儲於什麼地方。
所以,在我們隊指針進行間接訪問之前,必須小心,確保它們已經被初始化!
NULL指針
標準定義了NULL指針,它作爲一個特殊的指針變量,表示不指向任何東西。
要使一個指針變量未NULL,我們可以給它賦一個零值。
對指針進行解引用操作可以獲得它所指向的值。由於NULL指針並未指向任何東西,所以對NULL指針進行解引用操作是非法的。
在對指針進行解引用之前,必須確保它並非NULL指針。
指針運算
算術運算
指針支持的算術運算只限於兩種形式:
指針 ± 整數
- 這類表達式的結果類型也是指針。
- 但是存在一個問題,即如果我們將指針加1,那麼運算結果是指針指向的內存中的下一位、下一個字節、下一個字中的哪個呢?答案都是否定的。
當一個指針和一個整數量執行算術運算時,整數在執行加法運算前始終會根據合適的大小進行調整。這個合適的大小就是指針所指向類型的大小,調整就是把整數值和合適的大小相乘。
標準定義這種形式只能用於指向數組中某個元素的指針,這是由於數組中的元素存儲於連續的內存位置中,後面元素的地址大於前面元素的地址。因此:
對一個指針加1使它指向數組中下一個元素。
- 對一個指針減3使它向左移3個元素。
#include <stdio.h> #define N_VALUES 5 int main() { float value[N_VALUES] = {3.14,3.15,3.16,3.17,3.18}; for (int i = 0; i < N_VALUES; ++i) { printf("%f" , value[i]); } float *vp; for (vp = value ; vp < &value[N_VALUES] ; ++vp) *vp = 0; for (int i = 0; i < N_VALUES; ++i) { printf("%f" , value[i]); } }
指針 - 指針
- 只有當兩個指針都指向同一個數組中的元素時,才允許從一個指針減去另一個指針。
- 兩個指針相減的結果的類型是ptrdiff_t,它是一種有符號整數類型。
- 減法運算的值是兩個指針在內存中的距離(以數組元素的長度爲單位,而不是以字節爲單位),因爲減法運算的結果將除以數組元素類型的長度。
關係運算符
用下列關係操作符對兩個指針值進行比較是可能的:
< <= > >=
前提是它們都指向同一個數組中的元素。
根據你所使用的操作符,比較表達式將告訴你哪個指針指向數組中更前或更後的元素。