網站首頁 編程語言 正文
指針是什么?
指針(Pointer)是一個特殊的變量,它里面存儲的數值被解釋成為內存里的一個地址。
換句話說就是可以通過指針找到以它為地址的內存單元。
理解:內存圖解。
指針是個變量,存放內存單元的地址(編號)。
int main(){ int a = 10;//在內存中開辟空間存儲 int* p = &a;//先對變量a取出它的地址,可以使用&操作。 //將a的地址存放在p變量中國,p就是一個指針變量 }
小結:指針就是變量,內容是地址。(存放在指針中的值被當做地址處理)
指針的大小
- 在32為計算機上指針大小4字節。
- 在64為計算機上指針大小8字節。
指針和指針變量
關于地址
printf("%p \n",&a);//%p地址格式 &a取a的地址
int* p = &a; //int*指針類型 //p 指針變量 //&a 取地址
使用
*p //解引用操作符 int a =10; //在內存中存儲10 還有char*等類型 int* p = &a;//定義指針,位置為a的內存 *p = 20; //更改指針指向內存的 值 printf("a= %d",a);//結果為a=20
int* p的理解 p是int類型的一個指針(僅此而已),一般*p指向的也是一個int型的
1. 指針類型決定了指針進行解引用操作的時候,能訪問空間的大小
int main(){ int n = 0x112233; char* p = (char*)&n; int* pi = &n; *pc = 0; //在調試的過程中觀察內存的變化。 *pi = 0; return 0; }
int*; *p可以訪問4個字節。 char*; *p可以訪問1個字節。 double*; *p可以訪問8個字節。
原因?是類型本身所需的內存空間就是指針可以控制的空間。
意義:使用時選用合適的指針類型進行定義
2. 指針加減整數
int main(){ int a = 0x11223344; int* p1 = &a; char* p2 = &a; printf("%p\n",p1); printf("%p\n",p1+1); printf("%p\n",p2); printf("%p\n",p2+1); return 0; }
int類型時0C->10 變化4, char類型時0C->0D 變化1。
理解:指針加一不是指向下一個緊挨著的地址,是指向下一個指針變量對應的類型變量開始的地址。
意義?指針類型決定了:指針走一步走多遠(指針的步長)
野指針
野指針就是指針指向的位置是不可知的(隨機的、不正確的、沒有明確限制的)
野指針的成因
1.指針未初始化
int main(){ int a;//局部變量不初始化,默認是隨機值 int *p;//局部的指針變如果沒有初始化,就被初始化為隨機值。}int main(){ int a;//局部變量不初始化,默認是隨機值 int *p;//局部的指針變如果沒有初始化,就被初始化為隨機值。 }
2.指針越界訪問
int main(){ int arr[10]; int *p = arr; for(int i = 0;i<12;i++){ p++; } //當指針的范圍超出數組的范圍時,p就是野指針。 }
3.指針指向的空間釋放
int main(){ int arr[10]; int *p = arr; for(int i = 0;i<12;i++){ p++; } //當指針的范圍超出數組的范圍時,p就是野指針。 }
解析:在main函數調用test()時,進入test()函數,int a語句開辟臨時的內存空間并將這個內存空間存儲為10;返回函數的時候返回的臨時的a的地址給*p,然后test函數已經在執行完test函數后結束,a的內存空間被銷毀。這時的*p就是指向的地址正確但是內容已經改變。
將未知位置的值進行修改是非常危險的
如何避免野指針
1.指針初始化
2.小心指針越界
3.指針指向內存釋放 即 指向NULL
4.指針只用之前檢查有效性
指針運算
1.指針加減整數
2.指針-指針
3.指針的關系運算
指針加減指針
int main(){ int arr[10] = {1,2,3,4,5,6,7,8,9,10}; int sz = sizeof(arr)/sizeof(arr[0]); int* p = arr; for(int i=0;i<sz;i++){ printf("%d ",*p); p = p+1;// p++ } int* p = &arr[9]; for(int i=0;i>0;i++){ printf("%d ",*p); p-=1;// p++ } return 0; }
指針-指針
int main(){ int arr[10]={1,2,3,4,5,6,7,8,9,10}; printf("%d",&arr[9]-&arr[0]);//輸出9 中間元素的個數。 printf("%d",&arr[0]-&arr[9]);//輸出-9 return 0; }
指針減指針必須是自己減去自己。否則結果不可預知。
指針實現strlen()
int my_strlen(char* str){ char* start = str; char* end = str; while(*end != '\0'){ end++; } return ; } int main(){ char arr[] = "hello"; int len = my_strlen(arr); printf("%d\n",len); return 0; }
指針的關系運算
int main(){ float values[5]; for(float* vp=&values[5];vp>&values[0];){ printf("haha "); *--vp = 0; } return 0; }
這里碰到了兩個問題 1. values[5]本身不屬于數組的部分。但是可以使用。經測試values[5]不會警告,但是values[-1]及以下或values[6]及以上都會報錯。2.指針的加減是類型位置的移動數組總也就是一個一個往過走。
for(float* vp=&values[5-1];vp>=&values[0];vp--){ printf("haha "); *vp = 0; }
這里在絕大多數的編譯器上是可以順利完成任務的,然而我們應該避免這第二種寫法,因為標準不能保證他是可行的。
標準規定:允許指向數組元素的指針和指針與指向數組最后一個元素后面的那個內存位置的指針比較,但是不允許與指向第一個元素之前的那個位置的指針進行比較。
指針和數組
int main(){ int arr[10]={0}; printf("%p\n",arr); //地址-首元素地址 printf("%p\n",&arr[0]); }
一般情況數組名都代表首元素的地址
除了:
1. &數組名 這時數組名代表整個數組的地址
2. sizeof(數組名) 這時也是代表整個數組。
二級指針
將第一層指針1想成變量,再取這個變量的地址存為一個指針2。那么指針2指向指針1,指針1指向原變量。原變量的地址存在了指針1中,指針1的地址存在了指針2中。
int main(){ int a = 10; int* pa = &a; int** ppa = &pa;//ppa就是二級指針。 //存在三級及以上指針,(無限套娃) }
指針數組、數組指針
指針數組其實是個數組,數組指針是個指針
指針數組:存放指針的數組
int a = 10; int b = 20; int c = 30; int* arr[3] = {&a,&b,&c};//指針數組
數組指針:指向數組的指針。
main(){
int a = 10;
int* pa = &a;
int** ppa = &pa;//ppa就是二級指針。
//存在三級及以上指針,(無限套娃)
}
### 指針數組、數組指針 指針數組其實是個數組,數組指針是個指針 <u>**指針數組**</u>:存放指針的數組 ~~~c int a = 10; int b = 20; int c = 30; int* arr[3] = {&a,&b,&c};//指針數組
數組指針:指向數組的指針。
總結
原文鏈接:https://blog.csdn.net/Tian_baby/article/details/122294828
相關推薦
- 2022-07-27 C++中this指針理解及作用_C 語言
- 2022-10-25 golang值接收者和指針接收者的區別介紹_Golang
- 2022-08-02 Python?的矩陣傳播機制Broadcasting和矩陣運算_python
- 2022-11-30 react源碼層探究setState作用_React
- 2022-05-25 Properties與ResourceBundle的基本使用以及區別
- 2022-05-14 linq中的分區操作符_實用技巧
- 2021-11-08 Linux常用硬盤管理相關命令介紹_Linux
- 2023-05-09 Linux?解壓縮文件到指定目錄_linux shell
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支