C語言中的指針

指針概念

指針是一個變量粗井,該變量的數(shù)值是地址枝哄,或者說愈犹,指針是一個數(shù)據(jù)對象键科。

類似于,int 類型變量的數(shù)值是整數(shù)漩怎。

與指針相關的運算符

間接運算符:*

ptr 指向 bath勋颖,ptr = &bath

獲取 bath 中存放的數(shù)值勋锤,val = * ptr饭玲。

上面兩句語句等價于 val = bath

地址運算符:&

后跟一個變量名時怪得,& 給出該變量的地址咱枉。

指針聲明

int * pi;

int 表明被指向的變量的類型是整型卑硫,* 表示該變量是一個指針徒恋。pi 所指向的值(*pi)int 類型,pi
類型是“指向 int 的指針”欢伏。

* 和指針名之間的空格是可選的入挣。

指針的輸出格式是 %p

使用指針在函數(shù)間通信

結合 PHP 中函數(shù)的引用賦值來理解硝拧。

變量的值在函數(shù)中改變還是全局改變径筏。

指針和數(shù)組

概念

在 C 中,對一個指針加 1 的結果是對該指針增加 1 個存儲單元(storage unit)障陶。對數(shù)組而言滋恬,地址會增加到下一個元素的地址,而
不是下一個字節(jié)抱究。歸納如下:

  1. 指針的數(shù)值就是它所指向的對象的地址恢氯。對于包含多個字節(jié)的數(shù)據(jù)類型,對象的地址通常是指其首字節(jié)的地址鼓寺。

  2. 在指針前運用運算符 * 可以得到該指針所指向的對象的數(shù)值勋拟。

  3. 對指針加1,等價于對指針的值加上它所指向的對象的字節(jié)大小妈候。

函數(shù)敢靡、數(shù)組和指針

聲明數(shù)組參量

下面的四種原型都是等價的

int sum(int *ar, int n);
int sum(int *, int);
int sum(int ar[], int n);
int sum(int [], int);

定義函數(shù)時,下面兩種形式等價

int sum(int * ar, int n)
{
}

int sum(int ar[], int n)
{
}

聲明形式參量時苦银,int *arint ar[] 都表示 ar 是指向 int 的指針啸胧。

sizeof 求變量赶站、指針、數(shù)組大小纺念。

使用指針參數(shù)

使用數(shù)組形參的函數(shù)需要知道數(shù)組的起點和終點亲怠。告知終點有兩種方法,一種是直接使用整數(shù)參量指明數(shù)組元素的個數(shù)柠辞,一種是用指針
指明數(shù)組的結束地址团秽。比如,

int sum(int * start, int * end);

若數(shù)組的元素個數(shù)是 SIZE叭首,那么习勤,* end 的值是 &start + SIZE(表示數(shù)組的最后一個元素后面的下一個元素)。

一元運算符 *++ 具有相等的優(yōu)先級別焙格,但它在結合時是從右向左進行的图毕。

指針操作

指針基本操作

  1. 賦值(assignment)。

通常使用數(shù)組名或地址運算符&進行地址賦值眷唉。地址應該和指針類型兼容予颤。

  1. 求職(value-finding)或取值(dereferencing)。

  2. 取指針地址冬阳。

  3. 將一個整數(shù)加給指針蛤虐。

  4. 增加指針的值。

  5. 從指針中減去一個整數(shù)肝陪。

  6. 減小指針的值驳庭。

  7. 求差值(Differencing)。指向同一個數(shù)組內(nèi)兩個元素的指針使用此運算氯窍。

  8. 比較饲常。兩個指針具有相同的類型。

對未初始化的指針取值

不能對未初始化的指針取值狼讨。例如

int * pt;   // 未初始化的指針
*pt = 5;

合法的代碼

int i = 5;
int * pt = &i;

或者

double * ptd;
ptd = (double)malloc(30 * sizeof(double));

指針和多維數(shù)組

例程

#include <stdio.h>
int main(void)
{
    int zippo[4][2] = {{2, 4}, {6, 8}, {1, 3}, {5, 7}};

    printf("    zippo = %p,    zippo + 1 = %p\n",
           zippo,    zippo + 1);
    printf("zippo[0] = %p, zippo[0] + 1 = %p\n",
           zippo[0],    zippo[0] + 1);
    printf("  *zippo = %p,   *zippo + 1 = %p\n",
           *zippo, *zippo + 1);
    printf("zippo[0][0] = %d\n", zippo[0][0]);
    printf(" *zippo[0] = %d\n", *zippo[0]);
    printf("   **zippo = %d\n", **zippo);
    printf("    zippo[2][1] = %d\n", zippo[2][1]);
    printf("*(*(zippo+2) + 1) = %d\n", *(*(zippo+2) + 1));

    return 0;
}

代碼見 E:\code\c\c_primer_plus_c\10_15_zippo1.c贝淤。

這段代碼中的疑點:*zippo[0]**zippo政供。

聲明指向二維數(shù)組的指針變量

正確的代碼

int (* pz)[2];  // 聲明一個指向二維數(shù)組pz[n][2]的指針 

錯誤的代碼

int * pax[2];   // 創(chuàng)建一個兩個指針的數(shù)組

指針兼容

int n = 5;
double x;
int * pi = &n;
double * pd = &x;
x = n;  // 隱藏的類型轉換
pd = pi;    // 編譯時錯誤

假如有如下聲明:

int * pt;
int (*pa)[3];
int ar1[2][3];
int ar2[3][2];
int **p2;   // 指向指針的指針

那么播聪,有如下結論:

pt = &ar1[0][0];    // 都指向int
pt = ar1[0];        // 都指向int 
pt = ar1;   // 非法
pa = ar1;   // 都指向int[3]
pa = ar2;   // 非法
p2 = &pt;   // 都指向 int *
*p2 = ar2[0];   // 都指向int。不理解
p2 = ar2;   // 非法鲫骗。不理解

保護數(shù)組內(nèi)容

對形參使用 const

如果不打算在函數(shù)中修改數(shù)組犬耻,在函數(shù)原型和函數(shù)定義中對參數(shù)使用 const 可以達到目的。例程如下:

int sum(const int ar[], int n);

int sum(const int ar[], int n)
{
    int i;
    int total = 0;
    
    for(i = 0; i < n; i++)
        total += ar[i];
        
    return total;
}

使用了 const执泰,在函數(shù)中試圖修改使用了 const 的參數(shù)時枕磁,編譯時會發(fā)現(xiàn)此錯誤。

有關 const 的其他內(nèi)容

使用 const 創(chuàng)建符號常量术吝。

const double PI = 3.14159;

指向常量的指針不能用于修改數(shù)值计济,但可以指向其他地址茸苇。

double rates[5] = {88.99, 100.12, 59.45, 183.11, 340.5};
const double * pd = rates;      // pd指向數(shù)組開始處

* pd = 29.89;   // 不允許
pd[2] = 222.22;     // 不允許 
rates[0] = 99.99;   // 允許,因為 rates 不是常量
pd++;   // 讓pd指向rates[1]沦寂,允許

將常量或非常量數(shù)據(jù)的地址賦給指向常量的指針是合法的学密。

double rates[5] = {88.99, 100.2, 59.45, 183.11, 340.5};
const double locked[4] = {0.08, 0.075, 0.0725, 0.07};
const double * pc = rates;  // 合法 
pc = locked;    // 合法 
pc = &rates[3]; // 合法 

只有非常量數(shù)據(jù)的地址才可以賦給普通的指針。

double rates[5] = {88.99, 100.2, 59.45, 183.11, 340.5};
const double locked[4] = {0.08, 0.075, 0.0725, 0.07};

double * pnc = rates;   // 合法 
pnc = locked;   // 非法 
pnc = &rates[3];    // 合法 

使用 const 保證指針不會指向別處传藏。

double rates[5] = {88.99, 100.2, 59.45, 183.11, 340.5};
double * const pc = rates;  // 指針指向數(shù)組的開始處
pc = &rates[2];     // 不允許 
*pc = 92.99;        // 可以 

使用 const 禁止修改所指向的數(shù)據(jù)腻暮。

double rates[5] = {88.99, 100.2, 59.45, 183.11, 340.5};
const double * const pc = rates;    // 指針指向數(shù)組的開始處
pc = &rates[2];     // 不允許 
*pc = 92.99;        // 不允許  

參考資料

《C Primer Plus(第五版)中文版》

  1. 指針簡介: P236-9.7
  2. 指針和數(shù)組: P254-10.3
  3. 函數(shù)、數(shù)組和指針: P256-10.4
  4. 指針操作: P260-10.5
  5. 指針和多維數(shù)組: P267-10.7
  6. 保護數(shù)組內(nèi)容: P263-10.6
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末毯侦,一起剝皮案震驚了整個濱河市哭靖,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌侈离,老刑警劉巖试幽,帶你破解...
    沈念sama閱讀 206,013評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異卦碾,居然都是意外死亡铺坞,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,205評論 2 382
  • 文/潘曉璐 我一進店門洲胖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來济榨,“玉大人,你說我怎么就攤上這事宾濒⊥榷蹋” “怎么了?”我有些...
    開封第一講書人閱讀 152,370評論 0 342
  • 文/不壞的土叔 我叫張陵绘梦,是天一觀的道長。 經(jīng)常有香客問我赴魁,道長卸奉,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,168評論 1 278
  • 正文 為了忘掉前任颖御,我火速辦了婚禮榄棵,結果婚禮上,老公的妹妹穿的比我還像新娘潘拱。我一直安慰自己疹鳄,他們只是感情好,可當我...
    茶點故事閱讀 64,153評論 5 371
  • 文/花漫 我一把揭開白布芦岂。 她就那樣靜靜地躺著瘪弓,像睡著了一般。 火紅的嫁衣襯著肌膚如雪禽最。 梳的紋絲不亂的頭發(fā)上腺怯,一...
    開封第一講書人閱讀 48,954評論 1 283
  • 那天袱饭,我揣著相機與錄音,去河邊找鬼呛占。 笑死虑乖,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的晾虑。 我是一名探鬼主播疹味,決...
    沈念sama閱讀 38,271評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼帜篇!你這毒婦竟也來了佛猛?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 36,916評論 0 259
  • 序言:老撾萬榮一對情侶失蹤坠狡,失蹤者是張志新(化名)和其女友劉穎继找,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體逃沿,經(jīng)...
    沈念sama閱讀 43,382評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡婴渡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,877評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了凯亮。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片边臼。...
    茶點故事閱讀 37,989評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖假消,靈堂內(nèi)的尸體忽然破棺而出柠并,到底是詐尸還是另有隱情,我是刑警寧澤富拗,帶...
    沈念sama閱讀 33,624評論 4 322
  • 正文 年R本政府宣布臼予,位于F島的核電站,受9級特大地震影響啃沪,放射性物質發(fā)生泄漏粘拾。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,209評論 3 307
  • 文/蒙蒙 一创千、第九天 我趴在偏房一處隱蔽的房頂上張望缰雇。 院中可真熱鬧,春花似錦追驴、人聲如沸械哟。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,199評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽暇咆。三九已至,卻和暖如春冠摄,著一層夾襖步出監(jiān)牢的瞬間糯崎,已是汗流浹背几缭。 一陣腳步聲響...
    開封第一講書人閱讀 31,418評論 1 260
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留沃呢,地道東北人年栓。 一個月前我還...
    沈念sama閱讀 45,401評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像薄霜,于是被迫代替她去往敵國和親某抓。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,700評論 2 345

推薦閱讀更多精彩內(nèi)容