目錄
1、什么是指針?
1.1 內(nèi)存
1.2 指針變量
二、指針和指針類型
1、指針類型
2、指針+整數(shù)
3、指針的解引用
三、野指針
1、野指針成因
(1) 指針未初始化
(2) 指針越界訪問
(3) 指針指向的空間釋放
2、如何規(guī)避野指針
四、指針運算
1、指針-指針
? ? ? ?本篇文章我們來了解C語言中指針的相關內(nèi)容,對于指針可以說是C語言學習中較難理解的內(nèi)容。本篇以了解指針為目的,從表層入手,淺析C指針!
1、什么是指針?
理解指針的?兩個要點:
- 指針是內(nèi)存中一個最小單元的編號,也就是地址。
- 平時我們口中所說的指針,通常指的是指針變量,是用來存放內(nèi)存地址的變量。
總結(jié):指針就是地址,口語中說的指針通常指的是指針變量。
1.1 內(nèi)存
學習指針首先要了解?內(nèi)存:
內(nèi)存是電腦上特別重要的存儲器,計算機中程序的運行都是在內(nèi)存中進行的。所以為了有效的使用內(nèi)存,就把內(nèi)存劃分成一個個小的內(nèi)存單元,每個內(nèi)存單元的大小是1個字節(jié)。為了能夠有效的訪問到內(nèi)存的每個單元,就給內(nèi)存單元進行了編號,這些編號被稱為該內(nèi)存單元的地址。(每個內(nèi)存單元都有地址)就好比電腦是我們的學校,內(nèi)存就是學校的一個宿舍樓,而一個內(nèi)存單元就代表宿舍樓中的一個宿舍,而宿舍的門牌號就表示一個地址。
對于32位的機器,假設有32根地址線,那么假設每根地址線在尋址的時候產(chǎn)生高電平(高電壓)和低電平(低電壓)就是(1或者0);那么32根地址線產(chǎn)生的地址就會是:2^32 也就是說32位機器能夠產(chǎn)生2的32次方個地址。每個地址標識一個字節(jié),那我們就可以給 (2^32^Byte == 2^32^/1024KB == 2^32^/1024/1024MB==2^32^/1024/1024/1024GB == 4GB) 4G的空間進行編址。同理64位機器,如果給64根地址線,那么將有能力管理2^32^×4GB的內(nèi)存空間。
?
1.2 指針變量
為了能夠更好的訪問內(nèi)存空間,我們可以通過
&
(取地址操作符)取出變量的內(nèi)存其實地址,把地址可以存放到一個變量中,這個變量就是指針變量。
#include <stdio.h>
int main()
{
int num = 10;//在內(nèi)存中開辟一塊空間
int *p = #//這里我們對變量a,取出它的地址,可以使用&操作符。
//num變量占用4個字節(jié)的空間,這里是將a的4個字節(jié)的第一個字節(jié)的地址存放在p變量
中,p就是一個之指針變量。
return 0; }
? ? ? ? ? ? ? ? ? ? ? ? ? ??
總結(jié):
指針變量是用來存放地址的,地址是唯一標示一個內(nèi)存單元的。
在32位的機器上,地址是32個0或者1組成二進制序列,那地址就得用4個字節(jié)的空間來存儲,所以 一個指針變量的大小就應該是4個字節(jié)。
在64位機器上,如果有64個地址線,那一個指針變量的大小是8個字節(jié),才能存放一個地址。
二、指針和指針類型
1、指針類型
char ?*pc = NULL;//字符指針?
int ? *pi = NULL;//整形指針?
short *ps =NULL;//短整型指針?
long ?*pl = NULL;//長整型指針?
float *pf = NULL;//單精度浮點型指針
double *pd = NULL;//雙精度浮點型指針?
? ? ? ? ? ? ? ? ? ? ? ? ?
其實:
char*
?類型的指針是為了存放?char
?類型變量的地址。short*
?類型的指針是為了存放?short
?類型變量的地址。int*
?類型的指針是為了存放?int
?類型變量的地址。
那指針類型的意義是什么?
2、指針+整數(shù)
示例代碼:
#include <stdio.h>
int main()
{
int n = 8;
char* pc = (char*)&n;
int* pi = &n;
printf("%p\n", &n);
printf("%p\n", pc);
printf("%p\n", pc + 1);
printf("%p\n", pi);
printf("%p\n", pi + 1);
return 0;
}
結(jié)果:
結(jié)論:
1. 指針類型決定了指針的步長(向前 / 向后 走一步多大距離)
2. char* 指針 + 1,意思是跳過一個字符,也就是向后走1個字節(jié)
3. short* 指針 + 1,向后走2個字節(jié)
4. int* 指針 + 1,意思是跳過1個整形,也就是向后走4個字節(jié)
5. double* 指針 + 1,意思是跳過一個double,也就是向后走8個字節(jié)
3、指針的解引用
示例代碼:
//演示實例
#include <stdio.h>
int main()
{
int n = 0x11223344;
char *pc = (char *)&n;
int *pi = &n;
*pc = 0;
*pi = 0;
return 0;
}
結(jié)果:
?結(jié)論:
指針類型決定了:指針解引用操作的時候,訪問幾個字節(jié)(權限)
- char* 的指針解引用訪問1個字節(jié)
- int * 的指針解引用訪問4個字節(jié)
- double* 的指針,解引用訪問8個字節(jié)
三、野指針
概念:?野指針就是指針指向的位置是不可知的(隨機的、不正確的、沒有明確限制的)
1、野指針成因
(1) 指針未初始化
#include <stdio.h>
int main()
{
int *p;//局部變量指針未初始化,就會默認為隨機值
*p = 10;
return 0;
}
(2) 指針越界訪問
#include <stdio.h>
int main()
{
int arr[5] = {0};
int *p = arr;
for(int i=0; i<=6; i++){
//當指針指向的范圍超出數(shù)組arr的范圍時,p就是野指針
*(p++) = i;
}
return 0;
}
(3) 指針指向的空間釋放
int* test()
{
int num = 100;
return #//出了函數(shù),這塊內(nèi)存就不屬于我們了,還給了操作系統(tǒng)
}
int main()
{
int* p = test();
*p = 200;
return 0;
}
注意:變量num為局部變量,生命周期從創(chuàng)建開始到出test函數(shù)結(jié)束,test函數(shù)調(diào)用結(jié)束后num會將空間還給操作系統(tǒng),此時回到主函數(shù)p的地址已經(jīng)被釋放,此時p就是野指針。
2、如何規(guī)避野指針
- 指針初始化(已知指向時明確初始化;未知初始化為NULL)
- 小心指針越界
- 指針指向空間釋放,及時置NULL
- 避免返回局部變量的地址
- 指針使用之前檢查有效性
示例代碼:
#include <stdio.h>
int main()
{
int *p = NULL;//未知指向初始化為NULL
int a = 10;
p = &a;//明確初始化
if(p != NULL)//為空指針不訪問(無效指針)
{
*p = 20;//不為空再訪問
}
return 0;
}
四、指針運算
例如:通過指針加整數(shù)遍歷數(shù)組元素
示例代碼:
int main()
{
int arr[5] = {1,2,3,4,5};
int* p = arr;
for (int i = 0; i < 5; i++)
{
printf("%d ", *(p + i));
}
return 0;
}
1、指針-指針
含義:指針和指針相減的絕對值等于指針和指針之間元素的個數(shù)。
前提:兩個指針相減的前提是:指針指向的同一塊連續(xù)的空間。文章來源:http://www.zghlxwxcb.cn/news/detail-577200.html
#include<stdio.h>
int main()
{
int arr[10] = {0};
printf("%d\n", &arr[9] - &arr[0]); //結(jié)果9
printf("%d\n", &arr[0] - &arr[9]); //結(jié)果-9
//兩個指針相減的前提是:指針指向的同一塊連續(xù)的空間
//int a = 5;
//char c = 'a';
//printf("%d\n", &a - &c);//錯誤,沒有指向同一塊連續(xù)的空間
return 0;
}
補充:指針+指針沒有意義。文章來源地址http://www.zghlxwxcb.cn/news/detail-577200.html
創(chuàng)作不易,如果本篇博客對您有一定的幫助,大家記得留言+點贊哦。
到了這里,關于【C語言】-- 一篇帶你了解指針,內(nèi)存,解引用的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!