C語言的靈魂——指針

C語言的靈魂—指針

指針是什么

在計算機(jī)科學(xué)中腮敌,指針(Pointer)是編程語言中的一個對象膜钓,利用地址桃煎,它的值直接指向(points to)存在電腦存儲器中另一個地方的值零蓉。由于通過地址能找到所需的變量單元笤受,可以說,地址指向該變量單元敌蜂。因此箩兽,將地址形象化的稱為“指針”≌潞恚總結(jié)來說汗贫,指針就是指向地址的變量!

指針的作用

c語言指針可以有效地表示復(fù)雜的數(shù)據(jù)結(jié)構(gòu)秸脱、動態(tài)分配內(nèi)存落包、高效地使用數(shù)組和字符串、使得調(diào)用函數(shù)時得到多個返回值等摊唇。指針的應(yīng)用往往與數(shù)組聯(lián)系在一起妥色,是最頻繁的,也是最基礎(chǔ)的遏片。參數(shù)傳遞時只需要拷貝地址值嘹害,提高程序的運(yùn)行效率撮竿。有效的表示數(shù)據(jù)結(jié)構(gòu),能動態(tài)分配內(nèi)存笔呀。

指針

指針的語法

指針變量的定義: 類型 * 指針變量名
&:表示取地址操作
*: 表示取地址中的值

怎么去理解指針

大家可能一時半會可能很難理解指針含義幢踏。我們的計算機(jī)都會有一個內(nèi)存,并且這個內(nèi)存的每一個部分有一個標(biāo)記表示它的位置许师,這個標(biāo)識就是我們的地址房蝉,地址對應(yīng)的區(qū)域存放的就是我們的數(shù)據(jù)(值)。就像我們住酒店微渠,酒店是內(nèi)存搭幻,門牌號是我們的地址,住在房間里的人就是我們的數(shù)據(jù)逞盆!

代碼示例

#include<stdio.h>

int main(){
    int num = 10;
    double num2 = 10.0;
    int * p ;
    p = &num;

    //這種不同類型的變量之前的操作是不合法的
    // p = &num2;

    printf("p = %p\n",p);
    printf("num = %d\n",num);
    printf("*p = %d\n",*p);

    // num 和 p代表的是同一個地址的數(shù)據(jù)檀蹋,
    // 當(dāng)使用 *p 去修改數(shù)據(jù)的時候,num代表的數(shù)據(jù)也會改變云芦!
    *p = 11;
    printf("p = %p\n",p);
    printf("num = %d\n",num);
    printf("*p = %d\n",*p);

    return 0;
}

/*
    運(yùn)行結(jié)果:
        p = 0x7ffee1eee7c8
        num = 10
        *p = 10
        p = 0x7ffee1eee7c8
        num = 11
        *p = 11
*/

通過以上代碼我們不難理解:指針變量中俯逾,p 存放的是地址,p 是取地址對應(yīng)的值舅逸。num 變量直接存放地址對應(yīng)的值桌肴!當(dāng)我們使用 *p 修改數(shù)據(jù)的時候,我們 num 的存放的值也會發(fā)生改變琉历!我們使用 & 符號即可取出變量的地址
舉個例子坠七,p 存放的是門牌號,
p 代表居住的客人旗笔,num 也是代表這個門牌號下居住的客人彪置,當(dāng)使用 *p 修改掉居住的人,num 也會發(fā)生相應(yīng)的改變换团,因為他們代表的都是這個門牌號下居住的人悉稠。&num 即代表取出這個客人的房間門牌號

什么是雙重(n重)指針

我們根據(jù)之前的解釋可以知道,每個變量在內(nèi)存中都有一個地址相對應(yīng)艘包。雙重指針實際上存放的全是地址的猛。

代碼示例

#include<stdio.h>

int main(){
    int num = 10;
    int * p;
    p = &num;

    // 雙重指針
    int  ** q;

    // 指針變量也是變量的一種,即 p 也是有對應(yīng)的地址
    // &p 即取 p 變量的地址
    q = &p;

    // p 變量存放的地址 想虎,即num變量的地址
    printf("p = %p\n",p);
    // p 變量自身的地址
    printf("p = %p\n",&p);
    // q 存放的地址就是 p 變量自身的地址
    printf("q = %p\n",q);
    // *p == num
    printf("*p = %d\n",*p);  
    // **q == *p == num
    printf("**q = %d\n",*p);

    return 0;
}

/*
    執(zhí)行結(jié)果:
        p = 0x7ffee910c7c8
        p = 0x7ffee910c7c0
        q = 0x7ffee910c7c0
        *p = 10
        **q = 10
*/

圖解

graph LR
    q --> p
    p --> num

n重指針

n重指針同理


數(shù)組實際上使用的就是指針卦尊,我們再學(xué)習(xí)下數(shù)組類型

指針函數(shù)和函數(shù)指針

指針函數(shù)

顧名思義,指針函數(shù)就是返回值為指針的函數(shù)

語法示例

#include <stdio.h>

int *fun(int a, int b, int *p)
{
    *p = a + b;
    return p;
}
int main()
{
    int *p;
    p = fun(10, 10, p);
    printf("%d \n", *p);
    return 0;
}
/*
    執(zhí)行結(jié)果:
        20
*/

函數(shù)指針

函數(shù)指針就是指向函數(shù)的指針舌厨。一個函數(shù)標(biāo)識符就表示了它的地址

示例代碼

#include <stdio.h>

int add(int a, int b)
{
    return a + b;
}

int sub(int a, int b)
{
    return a - b;
}

int (*fun)(int a, int b);

int main()
{
    // 函數(shù)指針用法一
    fun = add;
    //調(diào)用方法二
    printf("%d \n", fun(10, 10));

    //用法二
    fun = &sub;
    //調(diào)用方法一
    printf("%d \n", (*fun)(10, 10));
    return 0;
}
/*
    執(zhí)行結(jié)果:
        20
        0
*/

一維數(shù)組

語法規(guī)則

類型名 變量名 [數(shù)組大小]
字符串?dāng)?shù)組:C語言中一個字符串的界定范圍是 '\0',當(dāng)遇到'\0'時認(rèn)為字符串已經(jīng)結(jié)束

語法示例

#include<stdio.h>

int main(){
    char chs[100] = {'a','b','c','\0'};
    printf("chs = %s\n",chs);

    //指針版示例
    printf("point verion:\n");
    printf("chs = ");
    for(int i = 0; *(chs + i) != '\0';i ++){
        printf("%c",*(chs + i));
    }
    printf("\n");
    return 0;
}

/*
    運(yùn)行結(jié)果:
    chs = abc
    point verion:
    chs = abc
*/

我們從示例代碼中可以看到: chs[i] 等價于 * (chs + i)

二位數(shù)組

語法定義

類型名 數(shù)組變量名稱 [行數(shù)][列數(shù)]

代碼示例

#include <stdio.h>

int main()
{

    //未初始化的數(shù)組其值是不確定的
    int arr[7][7] = {0};

    //輸入行數(shù)
    printf("%lu\n", sizeof(arr) / sizeof(arr[0]));

    //輸出列數(shù)
    printf("%lu\n", sizeof(arr[0]) / sizeof(int));

    //打印數(shù)組信息 數(shù)組實際上就是二維指針
    for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
    {
        for (int j = 0; j < sizeof(arr[0]) / sizeof(int); j++)
        {
            printf("%d ", (*(arr + i) + j));
        }
        printf("\n");
    }

    // 打印數(shù)組的地址信息 可以看到岂却,數(shù)組實際上是一塊連續(xù)的地址空間
    for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)  
    {
        for (int j = 0; j < sizeof(arr[0]) / sizeof(int); j++)
        {
            printf("%p ", (*(arr + i) + j));
        }
        printf("\n");
    }
    return 0;
}

/*
    執(zhí)行結(jié)果:
    7
    7
    0 0 0 0 0 0 0
    0 0 0 0 0 0 0
    0 0 0 0 0 0 0
    0 0 0 0 0 0 0
    0 0 0 0 0 0 0
    0 0 0 0 0 0 0
    0 0 0 0 0 0 0
    0x7ffee5a9d700 0x7ffee5a9d704 0x7ffee5a9d708 0x7ffee5a9d70c 0x7ffee5a9d710 0x7ffee5a9d714 0x7ffee5a9d718
    0x7ffee5a9d71c 0x7ffee5a9d720 0x7ffee5a9d724 0x7ffee5a9d728 0x7ffee5a9d72c 0x7ffee5a9d730 0x7ffee5a9d734
    0x7ffee5a9d738 0x7ffee5a9d73c 0x7ffee5a9d740 0x7ffee5a9d744 0x7ffee5a9d748 0x7ffee5a9d74c 0x7ffee5a9d750
    0x7ffee5a9d754 0x7ffee5a9d758 0x7ffee5a9d75c 0x7ffee5a9d760 0x7ffee5a9d764 0x7ffee5a9d768 0x7ffee5a9d76c
    0x7ffee5a9d770 0x7ffee5a9d774 0x7ffee5a9d778 0x7ffee5a9d77c 0x7ffee5a9d780 0x7ffee5a9d784 0x7ffee5a9d788
    0x7ffee5a9d78c 0x7ffee5a9d790 0x7ffee5a9d794 0x7ffee5a9d798 0x7ffee5a9d79c 0x7ffee5a9d7a0 0x7ffee5a9d7a4
    0x7ffee5a9d7a8 0x7ffee5a9d7ac 0x7ffee5a9d7b0 0x7ffee5a9d7b4 0x7ffee5a9d7b8 0x7ffee5a9d7bc 0x7ffee5a9d7c0
*/

數(shù)組相關(guān)的函數(shù)

#include <stdio.h>
int main(){
    char old[100];
    char new[200];
    int n = 10;

    //字符數(shù)組操作函數(shù)
    //將舊數(shù)組的數(shù)據(jù)拷貝到的新的數(shù)組之中。舊數(shù)組的數(shù)據(jù)遇到了\0就停止復(fù)制。新數(shù)組的長度必須大于等于舊數(shù)組數(shù)據(jù)長度 + 1
    strcpy(new,old);

    ?//  將舊數(shù)組的前n位字符拷貝到新數(shù)組中躏哩。新數(shù)組的長度必須大于等于新數(shù)組原數(shù)據(jù)長度 + 舊數(shù)組數(shù)據(jù)長度 + 1
    strncpy(new,old,n);

    //兩個字符數(shù)組進(jìn)行比較署浩。首先從第一位開始逐位比較,按照字典序的大小進(jìn)行比較扫尺。遇到第一個不等的字符或者遇到了\0停止比較筋栋。等于返回0,new < old返回 -1正驻,new > old 返回 1
    strcmp(new,old);

    //將兩個字符串進(jìn)行連接弊攘。新數(shù)組的長度必須大于等于 新數(shù)組的數(shù)據(jù)長度 + 舊數(shù)組的數(shù)據(jù)長度 + 1
    strcat(new,old);

    return 0;
}

以上就是本期的全部內(nèi)容了,感謝你能看到這里姑曙。我們下期見襟交!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市伤靠,隨后出現(xiàn)的幾起案子捣域,更是在濱河造成了極大的恐慌,老刑警劉巖醋界,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件竟宋,死亡現(xiàn)場離奇詭異提完,居然都是意外死亡形纺,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進(jìn)店門徒欣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來逐样,“玉大人,你說我怎么就攤上這事打肝≈拢” “怎么了?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵粗梭,是天一觀的道長争便。 經(jīng)常有香客問我,道長断医,這世上最難降的妖魔是什么滞乙? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮鉴嗤,結(jié)果婚禮上斩启,老公的妹妹穿的比我還像新娘。我一直安慰自己醉锅,他們只是感情好兔簇,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般垄琐。 火紅的嫁衣襯著肌膚如雪边酒。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天狸窘,我揣著相機(jī)與錄音甚纲,去河邊找鬼。 笑死朦前,一個胖子當(dāng)著我的面吹牛介杆,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播韭寸,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼春哨,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了恩伺?” 一聲冷哼從身側(cè)響起赴背,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎晶渠,沒想到半個月后凰荚,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡褒脯,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年便瑟,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片番川。...
    茶點(diǎn)故事閱讀 38,724評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡到涂,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出颁督,到底是詐尸還是另有隱情践啄,我是刑警寧澤,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布沉御,位于F島的核電站屿讽,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏吠裆。R本人自食惡果不足惜伐谈,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望硫痰。 院中可真熱鬧衩婚,春花似錦、人聲如沸效斑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至奇昙,卻和暖如春护侮,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背储耐。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工羊初, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人什湘。 一個月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓长赞,卻偏偏與公主長得像,于是被迫代替她去往敵國和親闽撤。 傳聞我的和親對象是個殘疾皇子得哆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,627評論 2 350

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