【C语言】指针的基本知识
接著上次的函數的基本知識,今天我們來講一講🔍指針
目錄
一、指針的概念
二、指針變量
三、野指針
四、字符指針
五、指針與數組
六、指針數組
七、數組指針
?八、指針與函數
總結
一、指針的概念
1.1、變量和地址
所謂指針,也就是內存的地址;所謂指針變量,也就是保存了內存地址的變量。
總結:指針就是變量,用指針存放地址(口語中說的指針通常指的是指針變量)?
1.2、指針變量和指針的類型
指針變量就是一個變量,它存儲的內容是一個指針。在我們定義一個變量的時候,要確定它的類型。在定義指針變量時也是一樣的,必須確定指針類型。int 變量的指針需要用 int 類型的指針存儲,float 變量的指針需要用 float 類型的指針存儲。
?指針類型決定了:指針解引用的權限有多大與指針走一步走多大字節(步長)
整型指針+1跳過一個整型。字符指針+1跳過一個字符
二、指針變量
2.1、指針變量的定義及使用
(1)指針變量的定義
指針變量的定義形式如:數據類型 *指針名;例如:
int* x;//整型指針變量 float* f;//浮點型指針變量 char* ch;//字符型指針變量指針的變量名分別是:x;f和ch。而int*;float*與char*分別是他們中存儲的數據的類型。?
(2)指針變量的使用
取地址運算符&:單目運算符&是用來取操作對象的地址。例:&i 為取變量 i 的地址。對于常量表達式、寄存器變量不能取地址(因為它們存儲在存儲器中,沒有地址)。
指針運算符*(解引用運算符 ):與&為逆運算,作用是通過操作對象的地址,獲取存儲的內容。例:x = &i,x 為 i 的地址,*x 則為通過 i 的地址,獲取 i 的內容。
2.2、指針運算
(1)指針與整數的加減運算
指針變量的自增自減運算。指針加 1 或減 1 運算,表示指針向前或向后移動一個單元(不同類型的指針,單元長度不同)。
(2)指針減指針
前提是兩個指針指向同一個空間。
指針減指針得到兩個指針間的元素個數
例: Arr[9]指向9與10中間部分(下標)
三、野指針
3.1概念:
野指針就是指針指向的為止是不可知的(隨機的,不正確的,沒有明確限制的)
3.2野指針的成因
(1)指針未初始化
(2)指針越界
如圖:在第十次 訪問時,可以進入到循環,相當于從第10個點向后訪問4個字節,之后的字節不屬于原數組,則越界了,則稱為野指針。(只有在超出范圍后,在會發生崩潰)
//越界訪問 *int arr[10] ={ 0 }; int* p = arr; int i=0; for (i=0; i <= 10; i++)//共執行了11次,而arr數組總共只有10個元素 {*p = i;p++; }(3)指針指向的空間釋放
int* test()//局部變量 {int a = 10;return &a; } int main() {int *p=test();//返回值是a的地址,而局部變量在引用之后就會銷毀。*p = 20;return 0; }3.3如何規避野指針
1.指針初始化?
2.小心指針越界。
3.指針指向空間釋放即置NULL
4.指針使用之前檢查有效性。
四、字符指針
4.1字符指針類型 在指針的類型中我們知道有一種指針類型為字符指針 char* ; 一般使用: int main() {const char* pstr = "hello ";//這里是把一個字符串放到pstr指針變量里了嗎?printf("%s\n", pstr);return 0; } 本質是把字符串 hello首字符的地址放到了pstr中。4.2例題
int main() {char str1[] = "hello bit.";char str2[] = "hello bit.";const char *str3 = "hello bit.";const char *str4 = "hello bit.";if(str1 ==str2) printf("str1 and str2 are same\n");else printf("str1 and str2 are not same\n");if(str3 ==str4) printf("str3 and str4 are same\n");else printf("str3 and str4 are not same\n");return 0; }最終輸出的結果是
這里str3和str4指向的是一個同一個常量字符串。C/C++會把常量字符串存儲到單獨的一個內存區域。當幾個指針指向同一個字符串的時候,他們實際會指向同一塊內存。 但是用相同的常量字符串去初始化不同的數組的時候就會開辟出不同的內存塊。所以str1和str2不同,str3和str4不同。?
五、指針與數組
之前我們可以通過下標訪問數組元素,學習了指針之后,我們可以通過指針訪問數組的元素。在數組中,數組名即為該數組的首地址,結合上面指針和整數的加減,我們就可以實現指針訪問數組元素。
5.1、指針與二維數組
(1)二維數組的地址
int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}}; int *p=a[0];//此處的p內存放的數組a第一行的地址。5.2、多級指針
(1)多級指針(指向指針的指針)
指針變量作為一個變量也有自己的存儲地址,而指向指針變量的存儲地址就被稱為指針的指針,即二級指針。依次疊加,就形成了多級指針。
指針變量也是一種變量,也會占用存儲空間,也可以使用 &獲取它的地址。C語言不限制指針的級數,每增加一級指針,在定義指針變量時就得增加一個星號 *。p1 是一級指針,指向普通類型的數據,定義時有一個 *;p2 是二級指針,指向一級指針 p1,定義時有兩個*。例:假設有一個 int 類型的變量 a,p1是指向 a 的指針變量,p2 又是指向 p1 的指針變量,它們的關系如下圖所示:
六、指針數組
1.parr的第一個數組里放arr1的首元素地址
2.parr每個元素的類型是int*。
3.該數組里每個元素都是指針,所以它是一個指針數組
4.Parr[i][j],也可以寫成parr[i]+j,
5.相當于地址+j為向后挨個元素指向
七、數組指針
7.1、數組指針的定義
如以下語句:
int (*p)[10]; //解釋:p先和*結合,說明p是一個指針變量,然后指著指向的是一個大小為10個整型的數組。 //所以p是一個指針,指向一個數組,叫數組指針。 //這里要注意:[]的優先級要高于*號的,所以必須加上()來保證p先和*結合。?7.2、&數組名與數組名
讓我們看一段代碼
#include <stdio.h> int main() {int arr[10] = { 0 };printf("arr = %p\n", arr);printf("&arr= %p\n", &arr);printf("arr+1 = %p\n", arr+1);printf("&arr+1= %p\n", &arr+1);return 0; }?運行結果如下
根據上面的代碼我們發現,其實&arr和arr,雖然值是一樣的,但是意義應該不一樣的。
實際上: &arr 表示的是數組的地址,而不是數組首元素的地址。(細細體會一下)
本例中 &arr 的類型是: int(*)[10] ,是一種數組指針類型。
數組的地址+1,跳過整個數組的大小。?7.3、數組指針的使用
#include <stdio.h> void print_arr1(int arr[3][5], int row, int col)//形參用數組來接受 {int i = 0;for(i=0; i<row; i++){for(j=0; j<col; j++){printf("%d ", arr[i][j]);}}} void print_arr2(int (*arr)[5], int row, int col)//形參用數組指針來接受 {int i = 0;for(i=0; i<row; i++){for(j=0; j<col; j++){printf("%d ", arr[i][j]);}printf("\n");}} int main() {int arr[3][5] = {1,2,3,4,5,6,7,8,9,10};print_arr1(arr, 3, 5);//數組名arr,表示首元素的地址//但是二維數組的首元素是二維數組的第一行//所以這里傳遞的arr,其實相當于第一行的地址,是一維數組的地址//可以數組指針來接收print_arr2(arr, 3, 5);return 0; }?八、指針與函數
8.1、函數指針的定義??
returnType (*pointerName)(param list);
其中,returnType 為函數返回值類型,pointerNmae 為指針名稱,param list 為函數參數列表。參數列表中可以同時給出參數的類型和名稱,也可以只給出參數的類型,省略參數的名稱,這一點和函數原型非常類似。
注意( )的優先級高于*,第一個括號不能省略,如果寫作returnType *pointerName(param list);就成了函數原型,它表明函數的返回值類型為returnType *。
8.2、指向函數的指針int (*pf[4])(int,int)={Add,Sub,Mul,Div};
函數指針數組,在函數指針的基礎上,將指針變為指針數組
總結
以上就是初階指針的基本內容了!!!!非常感謝你能看到這里!
如果你覺得你有些想法和我一樣,想和我一起提升自己可以關注私信我,與我一起進步,一起共同努力!!!!!
總結
以上是生活随笔為你收集整理的【C语言】指针的基本知识的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: uniapp聊天页nvue开发踩坑记录
- 下一篇: 向鼠标右键添加菜单,例:向鼠标右键添加g