校園網(wǎng)站建設(shè)論文域名大全查詢
你是真的“C”——詳解指針知識(shí)😎
- 前言🙌
- 1、 指針是什么?🙌
- 2、指針和指針類型🙌
- 2 、1指針+-整數(shù)
- 2 、 2指針的解引用
- 3、 野指針🙌
- 3、 1野指針成因
- 3、 2如何規(guī)避野指針
- 4、指針運(yùn)算🙌
- 4、1 指針+-整數(shù)
- 4、2 指針-指針
- 4、3 指針的關(guān)系運(yùn)算
- 5、指針和數(shù)組🙌
- 6 、 二級(jí)指針🙌
- 7、指針數(shù)組🙌
- 總結(jié)撒花💞

? ?
😎博客昵稱:博客小夢(mèng)
😊最喜歡的座右銘:全神貫注的上吧!!!
😊作者簡介:一名熱愛C/C++,算法等技術(shù)、喜愛運(yùn)動(dòng)、熱愛K歌、敢于追夢(mèng)的小博主!
😘博主小留言:哈嘍!😄各位CSDN的uu們,我是你的博客好友小夢(mèng),希望我的文章可以給您帶來一定的幫助,話不多說,文章推上!歡迎大家在評(píng)論區(qū)嘮嗑指正,覺得好的話別忘了一鍵三連哦!😘
前言🙌
? ? 哈嘍各位友友們😊,我今天又學(xué)到了很多有趣的知識(shí),現(xiàn)在迫不及待的想和大家分享一下!😘我僅已此文,和大家分享C語言中指針相關(guān)的知識(shí)點(diǎn)~ 都是精華內(nèi)容,可不要錯(cuò)過喲!!!😍😍😍
1、 指針是什么?🙌
在學(xué)習(xí)指針之前,首先要知道指針是什么?,其實(shí),指針理解起來可以概括為一下兩個(gè)要點(diǎn):
- 指針是內(nèi)存中一個(gè)最小單元的編號(hào),也就是地址
- 平時(shí)口語中說的指針,通常指的是指針變量,是用來存放內(nèi)存地址的變量
總結(jié):指針就是地址,口語中說的指針通常指的是指針變量。 - 指針變量:我們可以通過&(取地址操作符)取出變量的內(nèi)存起始地址,把地址可以存放到一個(gè)變量中,這個(gè)變量就是指針變量 。
舉個(gè)栗子輔助理解:
#include <stdio.h>
int main()
{int a = 10;//在內(nèi)存中開辟一塊空間int* p = &a;return 0;}
知識(shí)點(diǎn)分析:
- 這里我們對(duì)變量a,取出它的地址,可以使用&操作符。
- a變量占用4個(gè)字節(jié)的空間,這里是將a的4個(gè)字節(jié)的第一個(gè)字節(jié)的地址存放在p變量
- 中,p就是一個(gè)之指針變量。
小結(jié)一下:
指針變量,用來存放地址的變量。(存放在指針中的值都被當(dāng)成地址處理)。
? ?那么,一個(gè)內(nèi)存單元要分配多大的空間呢?又是怎么對(duì)這些內(nèi)存進(jìn)行編地址的呢?無數(shù)的先輩對(duì)此進(jìn)行探討分析,最終認(rèn)為一個(gè)內(nèi)存單位分配一個(gè)字節(jié),并分配一個(gè)地址是比較合適的。對(duì)于32位的機(jī)器,,假設(shè)有32根地址線,那么假設(shè)每根地址線在尋址的時(shí)候產(chǎn)生高電平(高電壓)和低電平(低電壓)就是(1或者0)。那么這里就有2的32次方個(gè)地址。同樣的方法,那64位機(jī)器,如果給64根地址線,那能編址就有2的64次方的地址。
簡單的概括來說:
在32位的機(jī)器上,地址是32個(gè)0或者1組成二進(jìn)制序列,那地址就得用4個(gè)字節(jié)的空間來存儲(chǔ),所以
一個(gè)指針變量的大小就應(yīng)該是4個(gè)字節(jié)。
那如果在64位機(jī)器上,如果有64個(gè)地址線,那一個(gè)指針變量的大小是8個(gè)字節(jié),才能存放一個(gè)地
址。
總結(jié):
- 指針變量是用來存放地址的,地址是唯一標(biāo)示一個(gè)內(nèi)存單元的。
- 指針的大小在32位平臺(tái)是4個(gè)字節(jié),在64位平臺(tái)是8個(gè)字節(jié)
2、指針和指針類型🙌
我們都知道,變量有不同的類型,整形,浮點(diǎn)型等。那指針有沒有類型呢?準(zhǔn)確的說是有的。指針的定義方式是: type + * 。
舉些栗子大家就知道啦:
char* 類型的指針是為了存放 char 類型變量的地址。
short* 類型的指針是為了存放 short 類型變量的地址。
int* 類型的指針是為了存放 int 類型變量的地址。
那指針類型的意義是什么?
2 、1指針±整數(shù)
這里通過畫圖的方式幫助大家輔助理解正指針加減運(yùn)算的規(guī)律:
總結(jié):指針的類型決定了指針向前或者向后走一步有多大(距離)
2 、 2指針的解引用
那么指針的解引用和指針的類型有沒有什么關(guān)聯(lián)呢?這里還是通過畫圖的方法幫助大家理解:
總結(jié):
指針的類型決定了,對(duì)指針解引用的時(shí)候有多大的權(quán)限(能操作幾個(gè)字節(jié))。
比如: char* 的指針解引用就只能訪問一個(gè)字節(jié),而 int* 的指針的解引用就能訪問四個(gè)字節(jié)。
3、 野指針🙌
按照教科書上的解釋概念: 野指針就是指針指向的位置是不可知的(隨機(jī)的、不正確的、沒有明確限制的)。按照我的理解,野指針其實(shí)就像是一條沒有被繩子拴住的野狗,到處亂串,當(dāng)使用它時(shí)(解引用),就會(huì)有危險(xiǎn)。
3、 1野指針成因
對(duì)于野指針存在的原因分析,比較常見的可以歸納為以下幾個(gè):
- 指針未初始化
- 指針越界訪問
- 指針指向的空間釋放
指針未初始化導(dǎo)致野指針,這里舉個(gè)栗子分析以下:
#include <stdio.h>
int main()
{ int *p;*p = 20;return 0;
}
小結(jié):局部變量指針未初始化,默認(rèn)為隨機(jī)值
指針越界訪問造成野指針,這里舉一個(gè)簡單的栗子:
#include <stdio.h>
int main()
{int arr[10] = {0};int *p = arr;int i = 0;for(i=0; i<=11; i++){*(p++) = i;}return 0;
}
小結(jié)一下:
這個(gè)數(shù)組一共只有10個(gè)元素,循環(huán)卻訪問到了第11個(gè)元素的位置。 當(dāng)指針指向的范圍超出數(shù)組arr的范圍時(shí),p就是野指針。
指針指向的空間釋放,當(dāng)再次訪問原空間時(shí),造成野指針。
int * test()
{int a = 10;return &a;
}int main()
{int* p = test();printf("%d", *p);return 0;
}
小結(jié)一下:
變量a是test內(nèi)的局部變量,當(dāng)運(yùn)行的時(shí)候出了這個(gè)函數(shù)時(shí),就會(huì)被銷毀掉,這里卻返回a變量的地址賦值給指針p,p去解引用操作不屬于程序的空間,則造成了野指針的問題。
3、 2如何規(guī)避野指針
- 指針初始化
- 小心指針越界
- 指針指向空間釋放,及時(shí)置NULL
- 避免返回局部變量的地址
- 指針使用之前檢查有效性
4、指針運(yùn)算🙌
4、1 指針±整數(shù)
上面已經(jīng)探討了這個(gè)知識(shí)點(diǎn),這里就不做講解了。
4、2 指針-指針
這里舉一個(gè)模擬實(shí)現(xiàn)strlen函數(shù)的代碼:
#include<stdio.h>
#include<assert.h>
int my_strlen(const char* p)
{assert(p);char* str = p;while (*p != '\0'){p++;}return p - str;
}int main()
{char arr[] = "Hello bit!";printf("%d", my_strlen(arr));return 0;
}
這里的返回值就是指針 - 指針的典型體現(xiàn)啦。指針減去指針,得到的是兩個(gè)指針之間元素的個(gè)數(shù)。
4、3 指針的關(guān)系運(yùn)算
C語言的語法標(biāo)準(zhǔn)規(guī)定:
允許指向數(shù)組元素的指針與指向數(shù)組最后一個(gè)元素后面的那個(gè)內(nèi)存位置的指針比較,但是不允許與指向第一個(gè)元素之前的那個(gè)內(nèi)存位置的指針進(jìn)行比較。
5、指針和數(shù)組🙌
指針和數(shù)組是不是同一個(gè)東西?其實(shí)不是的。雖然我們常說數(shù)組名是首元素的地址,好像和指針有緊密的關(guān)系,但指針和數(shù)組是完全不一樣的兩個(gè)東西。
可見數(shù)組名和數(shù)組首元素的地址是一樣的。
結(jié)論:數(shù)組名表示的是數(shù)組首元素的地址
既然可以把數(shù)組名當(dāng)成地址存放到一個(gè)指針中,我們使用指針來訪問一個(gè)數(shù)組中的元素就成為可能。所以 p+i 其實(shí)計(jì)算的是數(shù)組 arr 下標(biāo)為i的地址。
那我們就可以直接通過指針來訪問數(shù)組,舉個(gè)栗子:
#include <stdio.h>
int main()
{int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };int* p = arr; int sz = sizeof(arr) / sizeof(arr[0]);int i = 0;for (i = 0; i < sz; i++){printf("%d ", *(p + i));}return 0;
}
6 、 二級(jí)指針🙌
指針變量也是變量,是變量就有地址,那指針變量的地址存放在哪里?其實(shí),還是存放到指針變量中。
這里舉個(gè)栗子輔助大家理解一下:
#include <stdio.h>
int main()
{int a = 10;//a是要在內(nèi)存中申請(qǐng)4個(gè)字節(jié)的空間的//一級(jí)指針int* pa = &a;// pa是指針變量,用來存放地址,也得向內(nèi)存申請(qǐng),申請(qǐng)4/8,存放變量a的地址//二級(jí)指針int** ppa = &pa;//ppa是指針變量,用來存放地址,也得向內(nèi)存申請(qǐng),申請(qǐng)4/8,存放一級(jí)指針地址int** * pppa = &ppa;//pppa是指針變量,用來存放地址,也得向內(nèi)存申請(qǐng),申請(qǐng)4/8,存放二級(jí)指針地址printf("%d\n", **ppa);return 0;
}
如圖所示:
對(duì)于二級(jí)指針的運(yùn)算有:
- *ppa 通過對(duì)ppa中的地址進(jìn)行解引用,這樣找到的是 pa , *ppa 其實(shí)訪問的就是 pa .
- **ppa 先通過 *ppa 找到 pa ,然后對(duì) pa 進(jìn)行解引用操作: *pa ,那找到的是 a .
7、指針數(shù)組🙌
指針數(shù)組,顧名思義就是數(shù)組。指針數(shù)組,是用來存放指針的數(shù)組。數(shù)組我們已經(jīng)知道整形數(shù)組,字符數(shù)組。那指針數(shù)組又是長什么樣的呢?
int* arr3[5];
上述就是一個(gè)指針數(shù)組,arr3是數(shù)組名,一共有5個(gè)元素,每個(gè)元素的類型時(shí)int*。
接下來舉幾個(gè)栗子輔助大家理解:
可以利用指針數(shù)組來模擬二維數(shù)組的打印,但是這里有個(gè)區(qū)別是,二維數(shù)組的每一行元素在內(nèi)存中是連續(xù)存放的,這里就不一定。
#include <stdio.h>
int main()
{int arr1[] = { 1,2,3,4,5 };int arr2[] = { 2,3,4,5,6 };int arr3[] = { 3,4,5,6,7 };int* ptr[] = {arr1, arr2, arr3};int i = 0;for (i = 0; i < 3; i++){int j = 0;for (j = 0; j < 5; j++){printf("%d ", ptr[i][j]);}printf("\n");}return 0;
}
程序運(yùn)行結(jié)果圖:
上述知識(shí)的一個(gè)綜合運(yùn)用栗子:
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };int i = 0;for (i = 0; i < 10; i++){printf("%d ", i[arr]);//i[arr] -- *(i+arr)//arr[i] -- *(arr+i)}//int* p = arr;//test(arr, 10);*(arr+i) -- *(p+i) -- arr[i]arr[i] --> *(arr+i) --> *(i+arr) -- i[arr]//for (i = 0; i < 10; i++)//{// printf("%p = %p\n", &arr[i], p+i);//}return 0;
}int main()
{int arr[3][5];//arr[i][j]//(*(arr+i))[j]//*(*(arr+i)+j)return 0;
}
總結(jié)撒花💞
? ?本篇文章旨在分享C語言詳解指針的相關(guān)知識(shí)點(diǎn)。希望大家通過閱讀此文有所收獲!😘如果我寫的有什么不好之處,請(qǐng)?jiān)谖恼孪路浇o出你寶貴的意見😊。如果覺得我寫的好的話請(qǐng)點(diǎn)個(gè)贊贊和關(guān)注哦~😘😘😘