C语言指针关键知识点总结
本文目錄
- 一、對星號 * 的總結(jié)
- 二、各種指針總結(jié)
- 1、數(shù)組指針
- 2、字符串指針
- 3、指針變量做函數(shù)參數(shù)
- 4、指針作為函數(shù)返回值
- 5、指針數(shù)組
- 6、二維數(shù)組指針
- 7、函數(shù)指針
- 三、指針對比
- 四、空指針NULL與NUL以及void指針
一、對星號 * 的總結(jié)
在我們目前所學(xué)到的語法中,星號主要有三種用途:
- 表示乘法,例如int a = 3, b = 5, c; c = a * b;,這是最容易理解的。
- 表示定義一個指針變量,以和普通變量區(qū)分開,例如int a = 100; int *p = &a;。
- 表示獲取指針指向的數(shù)據(jù),是一種間接操作,例如int a, b, *p = &a; *p = 100; b = *p;。
二、各種指針總結(jié)
1、數(shù)組指針
如果一個指針指向了數(shù)組,我們就稱它為數(shù)組指針(Array Pointer)
重點(diǎn): 數(shù)組名是常量,它的值不能改變,而數(shù)組指針是變量(除非特別指明它是常量),它的值可以任意改變。也就是說,數(shù)組名只能指向數(shù)組的開頭,而數(shù)組指針可以先指向數(shù)組開頭,再指向其他元素。
2、字符串指針
表示方法
第一種方法直接使用字符數(shù)組表示字符串,聲明一個指針指向字符數(shù)組的首地址:
char str[] = "http://c.biancheng.net"; char *pstr = str;第二種方法是直接使用一個指針指向字符串(也稱字符串常量):
char *str = "http://c.biancheng.net";兩種表示方法的區(qū)別:
它們最根本的區(qū)別是在內(nèi)存中的存儲區(qū)域不一樣,字符數(shù)組存儲在全局?jǐn)?shù)據(jù)區(qū)或棧區(qū),第二種形式的字符串存儲在常量區(qū)。全局?jǐn)?shù)據(jù)區(qū)和棧區(qū)的字符串(也包括其他數(shù)據(jù))有讀取和寫入的權(quán)限,而常量區(qū)的字符串(也包括其他數(shù)據(jù))只有讀取權(quán)限,沒有寫入權(quán)限。
3、指針變量做函數(shù)參數(shù)
優(yōu)點(diǎn): 用指針變量作函數(shù)參數(shù)可以將函數(shù)外部的地址傳遞到函數(shù)內(nèi)部,使得在函數(shù)內(nèi)部可以操作函數(shù)外部的數(shù)據(jù),并且這些數(shù)據(jù)不會隨著函數(shù)的結(jié)束而被銷毀。
實例:
void swap(int *p1, int *p2)4、指針作為函數(shù)返回值
定義:C語言允許函數(shù)的返回值是一個指針(地址),我們將這樣的函數(shù)稱為指針函數(shù)。
實例:
char *strlong(char *str1, char *str2){if(strlen(str1) >= strlen(str2)){return str1;}else{return str2;} }注意: 用指針作為函數(shù)返回值時需要注意的一點(diǎn)是,函數(shù)運(yùn)行結(jié)束后會銷毀在它內(nèi)部定義的所有局部數(shù)據(jù),包括局部變量、局部數(shù)組和形式參數(shù),函數(shù)返回的指針請盡量不要指向這些數(shù)據(jù),C語言沒有任何機(jī)制來保證這些數(shù)據(jù)會一直有效,它們在后續(xù)使用過程中可能會引發(fā)運(yùn)行時錯誤。
5、指針數(shù)組
定義:如果一個數(shù)組中的所有元素保存的都是指針,那么我們就稱它為指針數(shù)組。
定義形式:
dataType *arrayName[length];[ ]的優(yōu)先級高于*,該定義形式應(yīng)該理解為:
dataType *(arrayName[length]);6、二維數(shù)組指針
定義實例:
int a[3][4] = { {0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11} }; int (*p)[4] = a;括號中的*表明 p 是一個指針,它指向一個數(shù)組,數(shù)組的類型為int [4],這正是 a 所包含的每個一維數(shù)組的類型。
使用指針p訪問二維數(shù)組中的每個元素
p指向數(shù)組 a 的開頭,也即第 0 行;p+1前進(jìn)一行,指向第 1 行。
*(p+1)表示取地址上的數(shù)據(jù),也就是整個第 1 行數(shù)據(jù)。注意是一行數(shù)據(jù),是多個數(shù)據(jù),不是第 1 行中的第 0 個元素,下面的運(yùn)行結(jié)果有力地證明了這一點(diǎn):
#include <stdio.h>
int main(){
int a[3][4] = { {0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11} };
int (p)[4] = a;
printf("%d\n", sizeof((p+1)));
}
運(yùn)行結(jié)果:
16
*(p+1)+1表示第 1 行第 1 個元素的地址。
((p+1)+1)表示第 1 行第 1 個元素的值。很明顯,增加一個 * 表示取地址上的數(shù)據(jù)。
指針數(shù)組和二維數(shù)組指針的區(qū)別
指針數(shù)組和二維數(shù)組指針在定義時非常相似,只是括號的位置不同:
int *(p1[5]); //指針數(shù)組,可以去掉括號直接寫作 int *p1[5]; int (*p2)[5]; //二維數(shù)組指針,不能去掉括號7、函數(shù)指針
定義:一個函數(shù)總是占用一段連續(xù)的內(nèi)存區(qū)域,函數(shù)名在表達(dá)式中有時也會被轉(zhuǎn)換為該函數(shù)所在內(nèi)存區(qū)域的首地址,這和數(shù)組名非常類似。我們可以把函數(shù)的這個首地址(或稱入口地址)賦予一個指針變量,使指針變量指向函數(shù)所在的內(nèi)存區(qū)域,然后通過指針變量就可以找到并調(diào)用該函數(shù)。這種指針就是函數(shù)指針。
函數(shù)指針的定義形式為:
returnType (*pointerName)(param list);returnType 為函數(shù)返回值類型,pointerNmae 為指針名稱,param list 為函數(shù)參數(shù)列表。參數(shù)列表中可以同時給出參數(shù)的類型和名稱,也可以只給出參數(shù)的類型,省略參數(shù)的名稱,這一點(diǎn)和函數(shù)原型非常類似。
實例:
#include <stdio.h>//返回兩個數(shù)中較大的一個 int max(int a, int b){return a>b ? a : b; }int main(){int x, y, maxval;//定義函數(shù)指針int (*pmax)(int, int) = max; //也可以寫作int (*pmax)(int a, int b)printf("Input two numbers:");scanf("%d %d", &x, &y);maxval = (*pmax)(x, y);printf("Max value: %d\n", maxval);return 0; }三、指針對比
辨析: 僅一個括號之差
int *p1[6]; //指針數(shù)組 int *(p2[6]); //指針數(shù)組,和上面的形式等價 int (*p3)[6]; //二維數(shù)組指針 int (*p4)(int, int); //函數(shù)指針常見指針變量的定義
| int *p; | p 可以指向 int 類型的數(shù)據(jù),也可以指向類似 int arr[n] 的數(shù)組。 |
| int **p; | p 為二級指針,指向 int * 類型的數(shù)據(jù)。 |
| int *p[n]; | p 為指針數(shù)組。[ ] 的優(yōu)先級高于 *,所以應(yīng)該理解為 int *(p[n]); |
| int (*p)[n]; | p 為二維數(shù)組指針。 |
| int *p(); | p 是一個函數(shù),它的返回值類型為 int *。 |
| int (*p)(); | p 是一個函數(shù)指針,指向原型為 int func() 的函數(shù)。 |
四、空指針NULL與NUL以及void指針
1、NULL空指針
NULL 是“零值、等于零”的意思,在C語言中表示空指針。從表面上理解,空指針是不指向任何數(shù)據(jù)的指針,是無效指針,程序使用它不會產(chǎn)生效果。
NULL 是在stdio.h中定義的一個宏,它的具體內(nèi)容為:
#define NULL ((void *)0)(void *)0表示把數(shù)值 0 強(qiáng)制轉(zhuǎn)換為void *類型,最外層的( )把宏定義的內(nèi)容括起來,防止發(fā)生歧義。從整體上來看,NULL 指向了地址為 0 的內(nèi)存,而不是前面說的不指向任何數(shù)據(jù)。
在進(jìn)程的虛擬地址空間中,最低地址處有一段內(nèi)存區(qū)域被稱為保留區(qū),這個區(qū)域不存儲有效數(shù)據(jù),也不能被用戶程序訪問,將 NULL 指向這塊區(qū)域很容易檢測到違規(guī)指針。
2、NUL
NUL 表示字符串的結(jié)束標(biāo)志 ‘\0’,它是ASCII碼表中的第 0 個字符。NUL 沒有在C語言中定義,僅僅是對 ‘\0’ 的稱呼,不能在代碼中直接使用。
3、void 指針
void 用在函數(shù)定義中可以表示函數(shù)沒有返回值或者沒有形式參數(shù),void * 表示指針指向的數(shù)據(jù)的類型是未知的。
void *表示一個有效指針,它確實指向?qū)崒嵲谠诘臄?shù)據(jù),只是數(shù)據(jù)的類型尚未確定,在后續(xù)使用過程中一般要進(jìn)行強(qiáng)制類型轉(zhuǎn)換。
C語言動態(tài)內(nèi)存分配函數(shù) malloc() 的返回值就是void *類型,在使用時要進(jìn)行強(qiáng)制類型轉(zhuǎn)換,請看下面的例子:
#include <stdio.h>int main(){//分配可以保存30個字符的內(nèi)存,并把返回的指針轉(zhuǎn)換為 char *char *str = (char *)malloc(sizeof(char) * 30);gets(str);printf("%s\n", str);return 0; }運(yùn)行結(jié)果:
c.biancheng.net↙
c.biancheng.net
總結(jié)
以上是生活随笔為你收集整理的C语言指针关键知识点总结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Redis 的info命令信息解释
- 下一篇: uniapp 聊天记录插入的两种方式