最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C語(yǔ)言超詳細(xì)講解指針的概念與使用

 更新時(shí)間:2022年05月05日 10:00:35   作者:嵌入式宇宙  
本文主要講解C語(yǔ)言中指針和字符串的關(guān)系以及指針和數(shù)組的關(guān)系,在看本文之前大家可以先看看博主之前的C語(yǔ)言基礎(chǔ)篇,先對(duì)C語(yǔ)言指針先有個(gè)基礎(chǔ)的了解,有助于對(duì)本文章有更深一步的了解

一、指針與一維數(shù)組

1. 指針與數(shù)組基礎(chǔ)

先說(shuō)明幾點(diǎn)干貨:

1. 數(shù)組是變量的集合,并且數(shù)組中的多個(gè)變量在內(nèi)存空間上是連續(xù)存儲(chǔ)的。

2. 數(shù)組名是數(shù)組的入口地址,同時(shí)也是首元素的地址,數(shù)組名是一個(gè)地址常量,不能更改。

3. 數(shù)組的指針是指數(shù)組在內(nèi)存中的起始地址,數(shù)組元素的地址是指數(shù)組元素在內(nèi)存中的其實(shí)地址。

      對(duì)于第一點(diǎn)數(shù)組中的變量在內(nèi)存空間上是連續(xù)的相信沒(méi)有什么疑問(wèn),這點(diǎn)在講解數(shù)組的時(shí)候就已經(jīng)提到過(guò)了。對(duì)于第二點(diǎn),可以得到,數(shù)組名就是一個(gè)地址,并且是整個(gè)數(shù)組的內(nèi)存起始地址。數(shù)組名一個(gè)是常量地址我們不能對(duì)數(shù)組名進(jìn)行賦值操作,數(shù)組名是數(shù)組的起始地址,數(shù)組的第一個(gè)元素的地址也是數(shù)組的起始地址,他們兩個(gè)在數(shù)值上是相等的。對(duì)于第三點(diǎn),舉個(gè)例子,假如定義一個(gè) int 類型變量 a,int 占四個(gè)字節(jié),假如他的第一個(gè)字節(jié)的地址是 0x00000010, 第四個(gè)字節(jié)的地址那么就是 0x00000013。而 &a 的地址是 a 的內(nèi)存空間上的首地址,即 &a 的值為 0x00000010。

      通過(guò)下面示例可以來(lái)證明一下上面講述的結(jié)論。

源代碼:

#include <stdio.h>
int main()
{
    int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    int b = 20;
    char *pb = &b;
    /*a是地址常量,不能被賦值*/
    //a = pb;
    /*在數(shù)值上 a &a[0] &a 的數(shù)值是相等的 */
    printf("a = %p, &a[0] = %p, &a = %p\n", a, &a[0], &a);
    printf("&b = %p, pb = %p, pb + 3 = %p\n", &b, pb, pb + 3);
    return 0;
}

運(yùn)行結(jié)果:

a = 0xbfb82f38, &a[0] = 0xbfb82f38, &a = 0xbfb82f38
&b = 0xbfb82f30, pb = 0xbfb82f30, pb + 3 = 0xbfb82f33

2. 指針與數(shù)組

以一個(gè)實(shí)例開始,數(shù)組的打印你會(huì)幾種方法?

源代碼:

#include <stdio.h>
int main()
{
    int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    int *p = a, i;
//1. 數(shù)組元素訪問(wèn)法
    for (i = 0; i < 10; i++) {
        printf("a[%d] = %-3d", i, a[i]);
    }
    putchar(10);  //等價(jià)于 putchar('\n'), 因?yàn)?\n 的 ASCII 碼就是 10
//2. 數(shù)組地址偏移訪問(wèn)法
    for (i = 0; i < 10; i++) {
        printf("a[%d] = %-3d", i, *(a + i));
    }
    putchar(10);
//3. 指針元素訪問(wèn)法
    for (i = 0; i < 10; i++) {
        printf("a[%d] = %-3d", i, p[i]);
    }
    putchar(10);
//4. 指針地址偏移訪問(wèn)法
    for (i = 0; i < 10; i++) {
        printf("a[%d] = %-3d", i, *(p + i));
    }
    putchar(10);
    return 0;
}

運(yùn)行結(jié)果:

a[0] = 1  a[1] = 2  a[2] = 3  a[3] = 4  a[4] = 5  a[5] = 6  a[6] = 7  a[7] = 8  a[8] = 9  a[9] = 10 
a[0] = 1  a[1] = 2  a[2] = 3  a[3] = 4  a[4] = 5  a[5] = 6  a[6] = 7  a[7] = 8  a[8] = 9  a[9] = 10

a[0] = 1  a[1] = 2  a[2] = 3  a[3] = 4  a[4] = 5  a[5] = 6  a[6] = 7  a[7] = 8  a[8] = 9  a[9] = 10
a[0] = 1  a[1] = 2  a[2] = 3  a[3] = 4  a[4] = 5  a[5] = 6  a[6] = 7  a[7] = 8  a[8] = 9  a[9] = 10

      從上面可以看到,如果一個(gè)指針p指向數(shù)組a,那么 a[i],*(a+i), p[i],*(p+i) 這四種寫法是完全等價(jià)的,都是訪問(wèn)數(shù)組中第 i+1 個(gè)元素。其實(shí)數(shù)組對(duì)于元素的訪問(wèn)根本上就是地址的偏移,a[i] 之所以能夠訪問(wèn)到第 i+1 個(gè)元素其實(shí)他所進(jìn)行的操作和 *(a+i) 是一樣的,都是在地址 a 的基礎(chǔ)上偏移 i 個(gè)單位的內(nèi)存單元進(jìn)行元素訪問(wèn)。a 是一個(gè)地址,p 也是一個(gè)地址,且當(dāng) p 指向 a 的時(shí)候,能夠以 a[i] 來(lái)訪問(wèn)第 i+1 元素,那么同理也能以 p[i] 的方式來(lái)訪問(wèn)第 i+1 個(gè)元素。同樣的 *(p+i) 也是以地址偏移的方式來(lái)進(jìn)行數(shù)組元素的訪問(wèn)。其實(shí)這幾種寫法唯一不同的就是 a 是地址常量,不能被賦值,也就是 a 不被允許再指向其他的內(nèi)存空間,而 p 是指針變量,可以被任意賦值,可以指向其他的內(nèi)存空間。

3. 一個(gè)思考

通過(guò)上面的講解請(qǐng)大家看一下下面程序應(yīng)該輸出多少?

#include <stdio.h>
int main()
{
    int a[10] = {1, 2, 3, 4, 5};
    int *p = &a[1];
    p[0] = 20;
    p[1] = 30;
    p[-1] = 10;
    printf("a[0] = %d, a[1] = %d, a[2] = %d\n", a[0], a[1], a[2]);
    return 0;
}

      其實(shí)大家可能或許能夠猜到程序的輸出結(jié)果是10,20,30。但是可能并不是所有人都能夠清楚的明白編譯器是怎么個(gè)處理邏輯的,在這里來(lái)為大家再做進(jìn)一步的講解,讓大家對(duì)指針和數(shù)組的關(guān)系有更深一步的認(rèn)識(shí)。

      上圖簡(jiǎn)單從地址偏移角度來(lái)畫出了指針的指向,大家先看右邊,地址 a 在數(shù)值上指向數(shù)組的首地址,那么 a+1 就是偏移了一個(gè) int 類型,也就是 4 字節(jié),所以 a+1 指向數(shù)組的第二個(gè)元素。大家再看左邊,p 指向 a[1] 的首地址,那么從指針變量 p 的角度來(lái)看,p[0] 就是他指向的元素 a[1],所以 p[0] 和 a[1] 是完全相等的,呢么 p[1] ,也可以寫成 *(p+1) 指向的就是 a[2] 元素的首地址,因?yàn)?p+1 要在 p 的基礎(chǔ)上偏移 4 字節(jié),p 指向 a[1] 的首地址,那么 p+1 就是指向 a[2] 的首地址,再用取值運(yùn)算符 *(p+1) 的值就是a[2] 的值也就是 3。p+1 理解了那么 p-1 也就不能理解了,他們兩個(gè)只是偏移的方向不同,p+1 是向右移,也就是地址增加的方向一定,而 p-1 是向左移,向地址減小的方向移動(dòng)。

二、指針與字符串

      C語(yǔ)言處理字符串通常實(shí)講字符串放在字符數(shù)組中,因?yàn)镃語(yǔ)言沒(méi)有字符串類型,而字符串在地址空間上是連續(xù)的,而數(shù)組元素在內(nèi)存空間上也是連續(xù),字符串就是若干字符的集合,所以就用字符數(shù)組來(lái)處理字符串,對(duì)于常量字符串也可以用指針對(duì)其直接指向操作。

      關(guān)于指針與字符串的關(guān)系大家可以先看看下面程序:

#include <stdio.h>
int main()
{
    char a[] = "hello world";
    char *b = "hello world";
    a[1] = 'z';
    //b[1] = 'z';   //error
    printf("a = %s\n", a);
    return 0;
}

      其實(shí)如上面注釋所示,可以對(duì) a 里面的元素進(jìn)行賦值操作,而不能對(duì) b 里面的元素進(jìn)行賦值操作。為什么呢?其實(shí)原因與內(nèi)存單元的分配有關(guān)。a 是一個(gè)局部變量數(shù)組,局部變量分配在棧上,棧上的內(nèi)容具有可讀可寫操作,所以對(duì) a 里面的元素進(jìn)行賦值操作沒(méi)有問(wèn)題。而 b 是一個(gè)指針,也是一個(gè)局部變量,但是 b 指向的是一個(gè)字符串常量,字符串常量存儲(chǔ)在只讀區(qū),只讀區(qū)里面的內(nèi)容只有讀權(quán)限而沒(méi)有寫權(quán)限,這點(diǎn)尤其注意,所以我們上述操作中對(duì) b 指向的內(nèi)容進(jìn)行寫操作編譯器是會(huì)報(bào)錯(cuò)的。報(bào)錯(cuò)內(nèi)容就是段錯(cuò)誤。導(dǎo)致段錯(cuò)誤的原因就是訪問(wèn)了非法內(nèi)存,非法內(nèi)存一般就是內(nèi)存地址不存在或者對(duì)于該塊地址沒(méi)有權(quán)限。

三、指針和二維數(shù)組

1. 指針數(shù)組與數(shù)組指針

      該部分主要講解指針數(shù)組與數(shù)組指針??赡軐?duì)于初學(xué)者而言對(duì)指針數(shù)組和數(shù)組指針比價(jià)容易弄混,其實(shí)記后面兩個(gè)字就可以,指針數(shù)組 后面兩個(gè)字是數(shù)組,說(shuō)明指針數(shù)組是一個(gè)數(shù)組,那么數(shù)組里面存儲(chǔ)的內(nèi)容就是前兩個(gè)字 指針。數(shù)組指針 后面兩個(gè)字是指針,說(shuō)明數(shù)組指針是一個(gè)指針,那么這個(gè)指針指向那里,前面兩個(gè)字就有體現(xiàn),數(shù)組指針指向一個(gè)數(shù)組。一句話概括之,指針數(shù)組是一個(gè)數(shù)組,數(shù)組里面每個(gè)元素存儲(chǔ)的是一個(gè)指針;數(shù)組指針是一個(gè)指針,是指向數(shù)組的指針。

指針數(shù)組的定義方法:

char a[5]; //字符數(shù)組

char *a[5]; //指針數(shù)組

數(shù)組指針的定義方法:

char a[5]; //字符數(shù)組

char (*a)[5] //數(shù)組指針

      上面數(shù)組指針和指針數(shù)組的定義方法很像,其實(shí)不管是這里的指針數(shù)組 數(shù)組指針 還是后面文章中會(huì)講解的 指針函數(shù) 函數(shù)指針,其實(shí)分辨他們有一個(gè)訣竅,那就是右左法則,何謂右左法則,即在運(yùn)算符的優(yōu)先級(jí)范圍內(nèi),先往右看,再往左看。打個(gè)比方,看上面定義的指針數(shù)組,先找到 a ,a 的右邊與 a 結(jié)合是一個(gè)數(shù)組,那么這個(gè)定義就是一個(gè)數(shù)組,是個(gè)什么樣的數(shù)組呢?再往左看,a 的左邊與 a 結(jié)合是一個(gè)指針,那么就是一個(gè)指針數(shù)組。再來(lái)看看數(shù)組指針,先找到 a,a 的右邊是一個(gè)括號(hào),有括號(hào)先看括號(hào)里面的內(nèi)容,也就是往左看,括號(hào)里面的內(nèi)容是一個(gè)指針,是個(gè)什么樣的指針呢?再往右看,是一個(gè)數(shù)組,所以就是數(shù)組指針。掌握了這個(gè)方法,不管是給出定義來(lái)辨別名字,還是告訴你名字讓其寫出定義都不在話下。

2. 指針數(shù)組

      指針數(shù)組是一個(gè)數(shù)組,里面每個(gè)成員都是指針,定義一個(gè)指針數(shù)組相當(dāng)于定義了多個(gè)指針變量的集合。 例如 int *a[3]; 這是一個(gè)指針數(shù)組,數(shù)組里面每個(gè)成員都是指向int類型地址的。為了讓大家更加熟悉指針數(shù)組的使用,大家請(qǐng)看下面這個(gè)例子:

源代碼:

#include <stdio.h>
int main()
{
    int a = 1, b= 2, c = 3;
    int *p[3];   //定義一個(gè)指針數(shù)組,數(shù)組里面有3個(gè)成員,每個(gè)成員都是指向int類型的指針。
    /*數(shù)組成員的初始化*/
    p[0] = &a;
    p[1] = &b;
    p[2] = &c; 
    /*通過(guò)指針改變其指向地址中的內(nèi)容*/
    *p[0] = 10;
    *p[1] = 20;
    *p[2] = 30;
    printf("a = %d, b = %d, c = %d\n", a, b, c);
    return 0;
}

運(yùn)行結(jié)果:

a = 10, b = 20, c = 30

      通過(guò)上面例子大家就不難發(fā)現(xiàn),定義好指針數(shù)組之后,數(shù)組成員的使用方法和普通指針的使用是一樣的,定義好一個(gè)指針數(shù)組唯獨(dú)就是可以一次性定義好多個(gè)指向相同類型的指針。其實(shí)大家想一下,我們當(dāng)時(shí)引入數(shù)組的時(shí)候說(shuō)C語(yǔ)言引入數(shù)組就是因?yàn)閿?shù)組可以一次性定義好多個(gè)具有相同類型的普通變量,其實(shí)這里的指針數(shù)組也是一樣的,不同的是,普通數(shù)組里面的成員都是普通變量,而指針數(shù)組里面的成員都是指針。

3. 數(shù)組指針

      數(shù)組指針是一個(gè)指針,指向一個(gè)數(shù)組的指針。 例如 int (*a)[3]; 這是一個(gè)數(shù)組指針,指向的是一個(gè)3列的數(shù)組,a+1 就相當(dāng)于步進(jìn)為1列,1列有3個(gè)int類型,相當(dāng)于步進(jìn)了 3 * 4 = 12(字節(jié))。示例如下:

源代碼:

#include <stdio.h>
int main(int argc, const char *argv[])
{
	int a[3][3] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
	/*定義數(shù)組指針*/
	int (*p)[3] = a;
	int (*q)[2] = a;
	/*數(shù)組指針步進(jìn)加1為1行*/
	printf("p = %p, p + 1 = %p\n", p, p+1);
	/*先對(duì)行指針進(jìn)行一次解引用就是普通指針,普通指針步進(jìn)就是指向的普通數(shù)據(jù)類型的大小*/
	*(*(p+1) + 1) = 56;
	printf("%d\n", a[1][1]);
	printf("q = %p, q + 1 = %p\n", q, q+1);
	*(*(q+1) + 1) = 56;
	printf("%d\n", a[1][0]);
	return 0;
}

運(yùn)行結(jié)果:

p = 0xbfc208ec, p + 1 = 0xbfc208f8
56
q = 0xbfc208ec, q + 1 = 0xbfc208f4
56

圖示如下:

      數(shù)組指針的步進(jìn)大家一定要清楚,步進(jìn)主要看定義時(shí)數(shù)組個(gè)數(shù)的大小,比如 int (*p)[3]; 步進(jìn)加1就是步進(jìn) int [3] 大小;int (*q)[2]; 步進(jìn)加1就是 int [2] 大小。數(shù)組指針就是行指針,因?yàn)閿?shù)組指針指向相同行的數(shù)組時(shí),指針偏移加1就是1行。

到此這篇關(guān)于C語(yǔ)言超詳細(xì)講解指針的概念與使用的文章就介紹到這了,更多相關(guān)C語(yǔ)言指針內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • MongoDB?C?驅(qū)動(dòng)程序安裝(libmongoc)?和?BSON?庫(kù)(libbson)方法

    MongoDB?C?驅(qū)動(dòng)程序安裝(libmongoc)?和?BSON?庫(kù)(libbson)方法

    這篇文章主要介紹了安裝?MongoDB?C?驅(qū)動(dòng)程序?(libmongoc)?和?BSON?庫(kù)?(libbson),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-09-09
  • 基于C++實(shí)現(xiàn)日期計(jì)算器的詳細(xì)教程

    基于C++實(shí)現(xiàn)日期計(jì)算器的詳細(xì)教程

    在現(xiàn)代社會(huì)中,計(jì)算器已經(jīng)進(jìn)入了每一個(gè)家庭,人們?cè)谏詈蛯W(xué)習(xí)中經(jīng)常需要使用到計(jì)算器,下面這篇文章主要給大家介紹了關(guān)于基于C++實(shí)現(xiàn)日期計(jì)算器的相關(guān)資料,需要的朋友可以參考下
    2022-06-06
  • 純C語(yǔ)言:貪心Prim算法生成樹問(wèn)題源碼分享

    純C語(yǔ)言:貪心Prim算法生成樹問(wèn)題源碼分享

    這篇文章主要介紹了貪心Prim算法生成樹問(wèn)題源碼,有需要的朋友可以參考一下
    2014-01-01
  • C語(yǔ)言 遞歸解決青蛙跳臺(tái)階問(wèn)題

    C語(yǔ)言 遞歸解決青蛙跳臺(tái)階問(wèn)題

    遞歸做為一種算法在程序設(shè)計(jì)語(yǔ)言中廣泛應(yīng)用?;竞x&#8203;是指函數(shù)/過(guò)程/子程序在運(yùn)行過(guò)程序中直接或間接調(diào)用自身而產(chǎn)生的重入現(xiàn)象。在計(jì)算機(jī)編程里,遞歸指的是一個(gè)過(guò)程:函數(shù)不斷引用自身,直到引用的對(duì)象已知
    2021-11-11
  • Visual C++中MFC消息的分類

    Visual C++中MFC消息的分類

    標(biāo)準(zhǔn)(窗口)消息:窗口消息一般與窗口內(nèi)部運(yùn)作有關(guān),如創(chuàng)建窗口,繪制窗口,銷毀窗口,通常,消息是從系統(tǒng)發(fā)到窗口,或從窗口發(fā)到系統(tǒng)
    2012-11-11
  • C語(yǔ)言文件讀寫操作介紹與簡(jiǎn)單示例

    C語(yǔ)言文件讀寫操作介紹與簡(jiǎn)單示例

    這篇文章主要給大家介紹了關(guān)于C語(yǔ)言文件讀寫操作的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • 用C語(yǔ)言完整實(shí)現(xiàn)2048游戲

    用C語(yǔ)言完整實(shí)現(xiàn)2048游戲

    2048是一款數(shù)字益智游戲,初始數(shù)字則是由2+2組成的基數(shù)4。在操作方面的不同則表現(xiàn)為一步一格的移動(dòng),變成更為爽快的一次到底。相同數(shù)字的方?jīng)r在靠攏、相撞時(shí)會(huì)相加。系統(tǒng)給予的數(shù)字方塊不是2就是4,玩家要想辦法在這小小的16格范圍中湊出2048這個(gè)數(shù)字方塊
    2021-11-11
  • C語(yǔ)言實(shí)現(xiàn)短字符串壓縮的三種方法詳解

    C語(yǔ)言實(shí)現(xiàn)短字符串壓縮的三種方法詳解

    這篇文章主要和大家分享一下smaz,shoco,unisox2三種短字符串壓縮算法,并分別探索它們各自的壓縮率與壓縮和解壓縮性能,需要的可以參考一下
    2022-08-08
  • Qt自定義控件實(shí)現(xiàn)多彩色儀表盤

    Qt自定義控件實(shí)現(xiàn)多彩色儀表盤

    這篇文章主要為大家詳細(xì)介紹了Qt自定義控件實(shí)現(xiàn)多彩色儀表盤,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-12-12
  • C++類與對(duì)象深入之引用與內(nèi)聯(lián)函數(shù)與auto關(guān)鍵字及for循環(huán)詳解

    C++類與對(duì)象深入之引用與內(nèi)聯(lián)函數(shù)與auto關(guān)鍵字及for循環(huán)詳解

    朋友們好,這篇播客我們繼續(xù)C++的初階學(xué)習(xí),現(xiàn)在對(duì)一些C++的入門知識(shí)做了些總結(jié),整理出來(lái)一篇博客供我們一起復(fù)習(xí)和學(xué)習(xí),如果文章中有理解不當(dāng)?shù)牡胤?還希望朋友們?cè)谠u(píng)論區(qū)指出,我們相互學(xué)習(xí),共同進(jìn)步
    2022-06-06

最新評(píng)論

汽车| 昭觉县| 正镶白旗| 竹山县| 大港区| 耿马| 乐陵市| 壶关县| 余姚市| 遵义县| 马鞍山市| 卢湾区| 崇阳县| 南郑县| 滕州市| 邯郸市| 丹阳市| 黄平县| 三亚市| 苗栗县| 辉南县| 正蓝旗| 云梦县| 福建省| 扬中市| 东明县| 衡阳县| 兴化市| 扶余县| 嘉黎县| 德江县| 阜宁县| 明星| 大渡口区| 毕节市| 北宁市| 易门县| 淅川县| 将乐县| 保靖县| 龙泉市|