C語言的靈魂——指針

一、指針簡介

1、什么是指針?

指針是一個變量,其值為另一個變量的地址,即內存地址的直接地址。做個比喻,假設將你比作變量,那么你身份證上的住址就是指針,根據你身份證上的地址可以找到你,即指針存的內容是你身份證上的住址。

指針有兩種含義,一是作為數據類型,二是作為實體。

指針作為實體,是一個用來保存一個內存地址的計算機語言中的變量。指針一般出現在比較底層的程序設計語言中,如C語言。高級語言如Java一般避免用指針,而是引用。指針作為數據類型,可以從一個函數類型、一個對象類型或者一個不完備類型中導出。從中導出的數據類型稱之為被引用類型(referenced type)。指針類型描述了一種對象,其值為對被引用類型的實體的引用。

指針可以用來有效地表示復雜的數據結構,可以用于函數參數傳遞并達到更加靈活使用函數的目的。使C語言程序的設計具有靈活、實用、高效的特點。

2、*與&操作符

取地址運算符(&):取變量的地址,即返回操作數的內存地址。&var 讀作"var 的地址"。

間接尋址運算符(*):返回操作數所指定地址的變量的值。

3、如何使用指針?

使用指針時會頻繁進行以下幾個操作:

  1. 定義一個指針變量;
  2. 把變量地址賦值給指針;
  3. 訪問指針變量中可用地址的值。

這些是通過使用一元運算符 * 來返回位于操作數所指定地址的變量的值。

#include <stdio.h>
int main (){
   int  var = 20;   /* 實際變量的聲明 */
   int  *ip;/* 指針變量的聲明 */
   ip = &var;  /* 在指針變量中存儲 var 的地址 */
   printf("Address of var variable: %x\n", &var  );
   /* 在指針變量中存儲的地址 */
   printf("Address stored in ip variable: %x\n", ip );
   /* 使用指針訪問值 */
   printf("Value of *ip variable: %d\n", *ip );
   return 0;
}

當上面的代碼被編譯和執行時,它會產生下列結果:

Address of var variable: bffd8b3c
Address stored in ip variable: bffd8b3c
Value of *ip variable: 20

4、指針運算符

C 指針是一個用數值表示的地址。因此,您可以對指針執行算術運算。可以對指針進行四種算術運算:++、--、+、-。

假設 ptr 是一個指向地址 1000 的整型指針,是一個 32 位的整數,讓我們對該指針執行下列的算術運算:

ptr++

在執行完上述的運算之后,ptr 將指向位置 1004,因為 ptr 每增加一次,它都將指向下一個整數位置,即當前位置往后移 4 個字節。這個運算會在不影響內存位置中實際值的情況下,移動指針到下一個內存位置。如果 ptr 指向一個地址為 1000 的字符,上面的運算會導致指針指向位置 1001,因為下一個字符位置是在 1001。

5、NULL 指針

在變量聲明的時候,如果沒有確切的地址可以賦值,為指針變量賦一個 NULL 值是一個良好的編程習慣。賦為 NULL 值的指針被稱為空指針。NULL 指針是一個定義在標準庫中的值為零的常量。請看下面的程序:
#include <stdio.h>
int main (){
int *ptr = NULL;
printf("ptr 的值是 %x\n", ptr );
return 0;
}

當上面的代碼被編譯和執行時,它會產生下列結果:

ptr 的值是 0

二、指針與數組

1、區別

C++/C程序中,指針和數組在不少地方可以相互替換著用,讓人產生一種錯覺,以為兩者是等價的。數組是連續分配一串單元,數目開始定義的時候就必須固定下來,看起來整潔,但是寫的程序是死程序,容易浪費內存。指針是存放一個地址值,表示指向某一個單元,可以用指針來索引單元。數組可以完成棧,堆,樹等等的操作,它在編程時候的好處是非常的靈活,在構建思路的時候有很大的靈活性。

2、指針數組與數組指針

指針數組:array of pointers,即用于存儲指針的數組,也就是數組元素都是指針。

數組指針:a pointer to an array,數組名本身就是一個指針,指向數組的首地址,即指向數組的指針。

int* a[4] ;   /* 指針數組      
                 表示:數組a中的元素都為int型指針     
                 元素表示:*a[i]   *(a[i])是一樣的,因為[]優先級高于*/
int (*a)[4]  ;/* 數組指針      
                 表示:指向數組a的指針
                 元素表示:(*a)[i]   */

#include <stdio.h>
int main(void)
{
    int c[4]={1,2,3,4};
    int *a[4]; //指針數組
    int (*b)[4]; //數組指針
    b=&c;
    //將數組c中元素賦給數組a
    for(int i=0;i<4;i++)
    {
        a[i]=&c[i];
    }
    //輸出看下結果
    printf("%d",*a[1]);//輸出2就對
    printf("%d",(*b)[2]);//輸出3就對
    return 0;
}

三、指針與字符串

C語言中沒有特定的字符串類型,我們通常是將字符串放在一個字符數組中。字符數組歸根結底還是一個數組,使用指針的方式來輸出字符串:

#include <stdio.h>
int main(){
    char str[] = "http://www.lxweimin.com/";
    char *pstr = str;
    int len = strlen(str), i;
    //使用*(pstr+i)
    for(i=0; i<len; i++){
        printf("%c", *(pstr+i));
    }
    printf("\n");
    //使用pstr[i]
    for(i=0; i<len; i++){
        printf("%c", pstr[i]);
    }
    printf("\n");
    //使用*(str+i)
    for(i=0; i<len; i++){
        printf("%c", *(str+i));
    }
    printf("\n");
    return 0;
}

四、指針與函數

函數指針:本身是一個指針,指向一個函數入口地址,通過該指針可調用其指向的函數,使用函數指針可實現回調函數。

#include <stdio.h>
void inc(int *val)
{
    (*val)++;
}
int main(void)
{
    void (*fun)(int *);
    int a=3;
    fun=inc;//fun是一個函數指針
    (*fun)(&a);
    printf("%d" , a);
}

指針函數:本身是一個函數,其返回值是一個指針。

#include <stdio.h>
float *find(float(*pionter)[4],int n);//函數聲明
int main(void)
{
     static float score[][4]={{60,70,80,90},{56,89,34,45},{34,23,56,45}};
     float *p;
     int i,m;
     printf("Enter the number to be found:");
     scanf("%d",&m);
     printf("the score of NO.%d are:\n",m);
     p=find(score,m-1);
     for(i=0;i<4;i++)
         printf("%5.2f\t",*(p+i));
     return 0;
 }
float *find(float(*pionter)[4],int n)/*定義指針函數*/
 {
     float *pt;
     pt=*(pionter+n);
     return(pt);
 }

五、指針與引用

  1. 引用總是指向一個對象,沒有所謂的 null reference 。所有當有可能指向一個對象也有可能不指向對象則必須使用指針。由于C++ 要求 reference 總是指向一個對象所以 reference要求有初值.由于沒有所謂的 null reference 所以在使用前不需要進行測試其是否有值,而使用指針則需要測試其的有效性。
  2. 指針可以被重新賦值而reference則總是指向最初或地的對象。
  3. 必須使用reference的場合.Operator[]操作符由于該操作符很特別地必須返回 [能夠被當做ssignment 賦值對象] 的東西,所以需要給他返回一個 reference。
  4. 其實引用在函數的參數中使用很經常。格式如下:
    void Get***(const int& a){} //這樣使用了引用又可以保證不修改被引用的值

區別:

  • 指針是一個實體指向一塊內存,它的內容是所指內存的地址;引用是某塊內存的別名;
  • 引用使用時無需解引用(*),指針需要解引用;
  • 引用只能在定義時被初始化一次,之后不可變;指針可變;
  • 引用“從一而終”;
  • 引用沒有 const,指針有 const,const 的指針不可變;
  • 引用不能為空,指針可以為空;
  • sizeof 引用”得到的是所指向的變量(對象)的大小,而“sizeof 指針”得到的是指針本身(所指向的變量或對象的地址)的大小;typeid(T) == typeid(T&) 恒為真,sizeof(T) == sizeof(T&) 恒為真,但是當引用作為成員時,其占用空間與指針相同(沒找到標準的規定);
  • 指針和引用的自增(++)運算意義不一樣。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,606評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,582評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,540評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,028評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,801評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,223評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,294評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,442評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,976評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,800評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,996評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,543評論 5 360
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,233評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,662評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,926評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,702評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,991評論 2 374

推薦閱讀更多精彩內容

  • 指針是C語言中廣泛使用的一種數據類型。 運用指針編程是C語言最主要的風格之一。利用指針變量可以表示各種數據結構; ...
    朱森閱讀 3,464評論 3 44
  • 前言 把《C++ Primer》[https://book.douban.com/subject/25708312...
    尤汐Yogy閱讀 9,532評論 1 51
  • 1.語言中變量的實質 要理解C指針,我認為一定要理解C中“變量”的存儲實質, 所以我就從“變量”這個東西開始講起吧...
    金巴多閱讀 1,801評論 0 9
  • 鮮花伴我行, 一路好春景。 人間四月天, 勝似在仙境。 --2017.4.14
    孫德娟欣欣兒閱讀 200評論 0 0
  • 剛下班,腦袋嗡嗡作響,耳朵里就像有一群知了在里面知知的叫,嗡嗡嗡嗡,知知知知,好不討厭。我知道這是神經性耳鳴,大概...
    鶯歌學飛閱讀 196評論 0 0