C语言基础指针知识点总结
指針入門,這一篇文章應該就夠了。如有錯誤或不足,還望多多指正。
文章目錄
- 一、 基本概念
- 1.1 地址
- 1.2 指針
- 1.3 為什么要使用指針這個東西呢
- 1.4 指針變量的定義
- 1.4.1 `*`
- 1.4.2 `&`
- 1.4.3 定義的關鍵
- 二、指針與數組
- 2.1 指向數組元素的指針
- 2.1.1 數組元素地址賦值給指針變量
- 2.1.2 指針運算
- 2.1.2.1 數組元素指針加或減
- 2.1.2.2 數組元素指針之間加減(注意,只有加減沒有乘除)
- 2.1.2.3
- 2.2 指針數組
- 三、指針與函數
- 3.1 返回值是指針的函數
- 3.2 指向函數的指針變量
- 四、指針和結構體
- 4.1 結構體變量成員的引用
- 4.2 指針與結構體
一、 基本概念
1.1 地址
地址:這里以int類型為例,
因為一個int類型4個字節Byte(32位和64位機器中)
所以可以簡單理解為這個int占了四個綠色小方框。
那么此時,這個int變量的地址就是1000,即第一個綠色小方框右邊的數字。
即就是:這個綠色方框在內存中所處的位置。
1.2 指針
指針:還是這個例子
那指針就是一個變量,比如這個變量名就叫p吧。
那這個p是個啥東西呢?
把這個1000存到p里去,即,把int類型變量a的地址存進新的變量p中。
那么p這個變量就是一個指向a的指針。
通俗理解下就是:
小明是個舔狗,喜歡小a,但是他比較害羞,不敢直接找小a。
所以小明就找到了小p。為什么找小p呢,因為小p有小a家的地址。
這樣小明就可以把給小a送的東西放小a家門口了。
這里的小a和小p就相當于例子中的int類型的a變量和指向a的指針p。
我只要找到了p就相當于找到了a
1.3 為什么要使用指針這個東西呢
首先我們要明白一直知識點:
需要說明一下的是指針類型存儲的是所指向變量的地址:
所以32位機器只需要32bit,而64位機器需要 64bit
由此可知,在一臺電腦上,所有指針大小都是一樣的。
那么,當我們定義了一些非常復雜龐大的結構體,比如這個結構體有50個字節(Byte)。
這時候,向函數中傳入參數的時候,是直接把這個50個字節的數據的副本傳遞到形參上快?
還是,直接傳遞32bit或者64bit的指針快呢??
很明顯,傳入指針可以大大大大提高運算的效率。
1.4 指針變量的定義
剛才說了,指針變量是來保存別的變量地址的一種變量。那該如何定義呢?
如何讓計算機一眼認出來這一串數字是地址,而不是普通的數字呢?
基本格式:
基本類型 *指針變量名 = &變量名;
(也可以先省略=后面的內容,先只定義,不賦值,但是還是建議定義的時候就進行賦值)
上面的代碼,我定義了兩個指針變量,一個是p一個是p2。
看見了兩個奇怪的符號*和&
1.4.1 *
這個符號,為取值運算符
啥是取值運算符呢?
就是,我現在有了指針,指針里存的是一個變量的地址,
我現在要通過地址取到這個變量的值。
注意:指針里存的是地址,就是通過這個地址找到這個地址住的誰。
舉例
比如上面的代碼中,pa這個變量存的是a的地址,變量a中存的是666。
那么*pa就可以相當于666。
所以可以明確一點。取值運算符會和指針變量連用。
為啥呢?
因為我們要通過地址取地址所指向的變量中存放的值呀!
如果還不明白沒關系,在說完&后我對上面的代碼解釋說明一下。
1.4.2 &
這個符號,為取地址運算符
這個就很簡單了。一個int變量名叫a存的是666
我給a前面加上&,變成
&a
那么這個&a就不是666啦。而是,存666的那個內存的地址。
所以我們又可以明確一點。取地址運算符會和一般變量(非指針變量)連用。
為啥呢?
因為指針變量已經是地址了,一般情況我們不需要取地址的地址,即指針的地址。
我們要的是什么。是普通變量的地址。
所以,下面這個代碼可以這么理解:
int a = 666; int *pa = &a;先定義一個int變量a 里面存著666.
第二行咱們叢后往前看:
&a是取地址,所以說,=后面就是一個地址。
然后我們理解pa = &a:
這其實就相當于pa里面存的是變量a的地址。
然后,pa前面加上*構成了*pa
*pa是什么,是把pa地址中存的整型變量a取出來了。
所以*pa其實就是666,相當于一個整型變量。
然后,最前面是int。int后面的*pa也可以理解為一個int類型的變量。
(這是我本人的一種理解方式,只希望大家能更快理解這個式子,可能底層并不是我這樣的,哈哈)
1.4.3 定義的關鍵
- 最好定義的時候就對指針進行賦值
- int類型的指針只能存int類型變量的地址,char類型的指針只能存char類型的地址,要對應起來
二、指針與數組
指針與數組分成兩個方面:
一、指向數組元素的指針
二、指針數組(數組元素是指針)
2.1 指向數組元素的指針
2.1.1 數組元素地址賦值給指針變量
首先我們要知道
數組名,其實就是這個數組下標為0的數組元素的地址。
這個地址也就是這個數組的地址。
所以,數組給指針復試和數組元素給指針賦值很不一樣。
因為,指針只能存地址。
數組名本身就保存的地址,所以就直接可以給指針變量賦值。
數組的元素保存的就是具體的內容了,可能為int可能為char。
所以,數組元素賦值的時候,就要先用取地址符&得到這個元素的地址,然后再給指針變量賦值。
2.1.2 指針運算
眾所周知,數組,存在內存中一片地址連續的區域中
即就是說,數組,在邏輯上是一個元素挨著一個元素,在物理存儲上也是一個元素挨著一個元素的。
2.1.2.1 數組元素指針加或減
所以,當指針變量指向數組元素時,指針變量加/減一個整數n,表示指針向后/前移動n個元素!
注意,這里+n是移動一個元素,不是移動n個字節
當然,移動幾個元素就指針的具體值就增加或減少這個幾個元素所占的字節數
比如:int 數組中,指針指向某個元素,然后給這個指針+2
那么這個指針本身的值就應該加幾?
一個int元素占4個字節,倆就是8個字節,
那么地址字節值就要加8
看例子:
int c[20]; int *p1 = &c[9]; p1--; p1+=3;2.1.2.2 數組元素指針之間加減(注意,只有加減沒有乘除)
相減得到的這個數字是這兩個地址之間相差的字節數。
然后,用這個字節數,除以每個元素所占的字節數。
就可以得出這兩個地址之間相差幾個元素。
2.1.2.3
我們在復習一下:
數組名,就是這個數組的首地址,也是這個數組中下標為0元素的地址。
好了,那如果我們把這個數組的首地址保存在一個指針變量中,然后對這個指針變量直接+或者-
這樣是不是就可以遍歷數組了呢?
C語言將數組元素中的[ ]稱為變址運算符
一維數組元素b[j]的表示形式等價于*(b+j)
(大家不要忘記*是取值運算符哦,就是把這個地址中存的具體的值取出來)
舉例:
int b[20],*p = b; //數組元素b[j]還有下面兩種表示方式 //*(p+j) //*(b+j) //p[j] 注意:指針變量也是可以帶下標的,但是一般只有在數組上才這么用**注意:**數組名b是符號常量,所以,不能給b賦值。這個b就類似于函數的名字一樣,我們不能隨便改變已經定義好的函數的名字。
空指針:
C語言設置了一個指針常量NULL,稱為空指針。空指針不指向任何存儲單元。
空指針可以賦值給任何指針類型的變量。
2.2 指針數組
整形數組中,數組元素都是整型
字符數組中,數組元素都是字符
指針數組中,數組元素都是指針
注意區分兩個概念:
int (*p)[5]; //這里*先與p結合,表示p是一個指針,這個指針指向這個數組,這個數組是int類型的數組int *p[5];//這個表示指針數組,每個元素都是指針,上面說過了三、指針與函數
3.1 返回值是指針的函數
指針函數:
函數的返回值的類型既可以是整型(若沒有設定,則默認為整型),實型,字符型,也可以是指針型。
返回值為指針類型的函數又稱為指針類型的函數,建成指針函數。
具體定義格式如下:
類型名 *函數名(參數表)
3.2 指向函數的指針變量
c語言的每個函數的編譯的時候,都分配了一段連續的內存空間和一個入口地址,
這個入口地址就稱為“指向函數的指針”,即函數指針。
可以用一個變量來存儲函數指針,這個變量就稱為“指向函數的指針變量”或者函數指針變量。
通過函數指針變量 就可以調用所指向的函數,改變它的值就可以動態調用不同的函數。
一般定義形式
類型說明符 (*變量名)()
eg:
- 函數指針變量定義時,并不指向哪一個具體的函數,而是指向空指針。
那如何通過函數指針變量調用函數呢?
那就是讓函數指針變量p指向一個具體的函數,即將某個函數的入口地址賦值給這個指針變量。
那一般函數的入口地址在哪里呢?
函數名就代表函數的入口地址,是函數指針類型的符號常量。(這里和數組有點類似,數組名也是數組的地址。)
//ok 比如現在有個函數,函數名叫abc,就可以對函數指針變量p賦值了 p = abc;那賦值給函數指針變量p以后,如何使用p來調用這個函數呢?
還記得我們的取值運算符*嗎?
本來調用函數應該是這樣的
函數名();
那現在,函數名的位置用*函數指針變量名來代替就可以啦
剩下的就和普通函數的使用方式基本一樣啦。
四、指針和結構體
4.1 結構體變量成員的引用
typedef struct student{char name[21];int age;char sex;float score; };student st1; //現在給第一個學生的年齡賦值 st1.age = 20; //普通結構體引用成員的時候使用. //.前面是定義的結構體變量,.后面是要引用的結構體中的成員4.2 指針與結構體
結構體類型是一種構造類型,與簡單類型(int、float和char等)一樣,也可以定義為指針變量,定義方法也相同。
typedef struct student{char name[21];int age;char sex;float score; }student,*stu; //這里解釋一下*stu,就是student類型的指針變量,即這個指針指向一個student結構體 stu q = null; //這里定義的這個p直接就是一個指針類型的變量,因為stu在typedef語句中就背定義為指針了student s; student *p = s; q = p; //下面有這幾種方法可以訪問student的成員age(別的成員訪問方式類似) s.age = 10; (*p).age = 10; p->age = 10; q->age = 10;**注意:**如果用結構體指針在不加取值運算符*的情況下想直接訪問結構體成員要用到->
總結
以上是生活随笔為你收集整理的C语言基础指针知识点总结的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 听说你也有拖延症快来看看这篇文章
- 下一篇: round在python是什么意思_细说