1.指針是什么
初學(xué)者都有一個疑問,那就是指針是什么?簡單的說,就是通過它能找到以它為地址的內(nèi)存單元。
地址指向了一個確定的內(nèi)存空間,所以地址形象的被稱為指針。
1
2
3
4
5
6
7
8
|
int main() { int a = 10; int * pa = &a; return 0; } //pa是用來存放地址(指針),所以pa是指針變量。 |
總結(jié):指針就是變量,用來存放地址的變量。(存放在指針中的值都被當(dāng)成地址處理)。
? 地址是唯一標(biāo)識一塊空間的。
? 指針的大小在32位平臺是4個字節(jié),在64位平臺是8個字節(jié)。
2.指針和指針類型
我們知道變量有不同的類型(整型、浮點型、字符型等),其實指針也是有不同類型的。
? 指針類型的意義1:
指針類型決定了指針解引用操作的時候,一次訪問幾個字節(jié)(訪問內(nèi)存的大小)
char*
指針解引用訪問1個字節(jié)
int*
指針解引用訪問四個字節(jié)
1
2
3
4
5
6
7
|
int main() { char * pc = &a; *pc = 0; return 0; } |
? 指針類型的意義2:
指針類型決定了,指針±整數(shù)的時候的步長(指針±整數(shù)的時候,跳過幾個字節(jié))
int*
指針+1 跳過四個字節(jié)
char*
指針+1 跳過一個字節(jié)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
int main() { int a = 10; int * pa = &a; char * pc = &a; printf ( "%p " , pa); printf ( "%p " , pc); printf ( "%p " , pa+1); printf ( "%p " , pc+1); return 0; } |
3.野指針
? 野指針就是指針指向的位置是不可知的(隨機的、不正確的、沒有明確限制的)。
3.1野指針成因
指針未初始化
1
2
3
4
5
6
7
8
|
int main() { int * p; //局部變量指針未初始化,默認(rèn)為隨機值 *p = 20; //通過p中存的隨機值作為地址,找到一個空間,這個空間不屬于我們當(dāng)前的程序 //就造成了非法訪問,p就是野指針 return 0; } |
指針越界訪問
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
int main() { int arr[10] = 0; int i = 0; int * p = arr; for (i =0; i <= 10; i++) { *p = i; p++; //當(dāng)指針指向的范圍超出數(shù)組arr的范圍時,p就是野指針 } return 0; } |
指針指向的空間釋放
1
2
3
4
5
6
7
8
9
10
11
12
13
|
int * test() { int a = 10; return &a; } int main() { int * p = test(); printf ( "%d " ,*p); return 0; } |
3.2如何規(guī)避野指針
- 指針初始化
- 小心指針越界
-
指針指向空間釋放即使置
NULL
- 避免返回局部變量的地址
- 指針使用之前檢查有效性
1
2
3
4
5
6
7
8
9
|
int main() { int a = 10; int * p = &a; //明確地初始化,確定指向 int * p2 = NULL; //不知道一個指針當(dāng)前應(yīng)該指向哪里時,可以初始化為NULL return 0; } |
4.指針的運算
4.1指針±整數(shù)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
#define N_VALUES 5 float values[N_VALUES]; float * vp; for (vp = &values[0]; vp < &values[N_VALUES];) { *vp++ = 0; } int main() { int arr[10] = {1,2,3,4,5,6,7,8,9,0}; int * p = &arr[9]; printf ( "%p " ,p); printf ( "%p " ,p-2); return 0; } |
4.2指針-指針
指針-指針 得到的數(shù)字的絕對值是指針和指針之間元素的個數(shù)
1
2
3
4
5
6
7
8
|
int main() { int arr[10] = { 1,2,3,4,5,6,7,8,9,0 }; printf ( "%d " , &arr[9] - &arr[0]); printf ( "%d " , &arr[0] - &arr[9]); return 0; } |
指針-指針 的前提是兩個指針指向同一塊區(qū)域
1
2
3
4
5
6
7
8
|
int main() { int arr[10] = {1,2,3,4,5,6,7,8,9,0}; char ch[5] = {0}; printf ( "%d " ,&arr[9] - &ch[0]); //err return 0; } |
應(yīng)用 求字符串長度
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
int my_strlen( char * s) { int count = 0; char * start = s; while (*s!= '' ) { s++; } return s - start; } int main() { char arr[] = "abcdef" ; int len = my_strlen(arr); printf ( "%d " , len); return 0; } |
4.3指針的關(guān)系運算
1
2
3
4
5
6
7
|
#define N_VALUES 5 float values[N_VALUES]; float *vp; for (vp = &values[N_VALUES]; vp > &values[0];) { *--vp = 0; } |
上述程序也可以寫成這樣
1
2
3
4
|
for (vp = &values[N_VALUES-1]; vp >= &values[0];vp--) { *vp = 0; } |
實際在絕大部分的編譯器上是可以順利完成任務(wù)的,然而我們還是應(yīng)該避免這么寫,因為標(biāo)準(zhǔn)并不保證它可行。
標(biāo)準(zhǔn)規(guī)定
? 允許指向數(shù)組元素的指針與指向數(shù)組最后一個元素后面的那個內(nèi)存位置的指針比較,但是不允許與指向第一個元素之前的那個內(nèi)存位置的指針進行比較。
5.指針和數(shù)組
數(shù)組 - 是一塊連續(xù)的空間,放的是相同類型的元素
數(shù)組大小和元素類型,元素個數(shù)有關(guān)系
指針(變量) - 是一個變量,放地址
指針變量的大小 是4(32bit)/8(64bit)
個byte
數(shù)組名確實是首元素地址
但是有兩個例外:
- sizeof(數(shù)組名) - 這里的數(shù)組名不是首元素的地址,是表示整個數(shù)組的,這里計算的是整個數(shù)組的大小,單位還是字節(jié)。
- &數(shù)組名 - 這里的數(shù)組名不是首元素的地址,是表示整個數(shù)組的,拿到的是整個數(shù)組的地址
1
2
3
4
5
6
7
|
int main() { int arr[10] = { 0 }; int sz = sizeof (arr); printf ( "%d " , sz); return 0; } |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
int main() { int arr[10] = { 0 }; int * p = arr; int i = 0; int sz = sizeof (arr) / sizeof (arr[0]); for (i = 0;i < sz;i++) { *(p + i) = i; } for (i = 0;i < sz;i++) { printf ( "%d " , *(p + i)); } return 0; } |
6.二級指針
我們都知道,指針變量是變量,是變量就有地址,那么指針變量的地址存放在哪里呢?
這就是我們要了解的二級指針。
1
2
3
4
5
6
7
8
9
|
int main() { int a = 10; int * p = &a; int ** pp = &p; //pp就是二級指針 **pp = 20; printf ( "%d " , a); //a = 20 return 0; } |
7.指針數(shù)組
? 從名字上來看,大家覺得指針數(shù)組是指針還是數(shù)組?
答案是數(shù)組,是存放指針的數(shù)組。
整型數(shù)組 - 存放整型的數(shù)組就是整型數(shù)組
字符數(shù)組 - 存放字符的數(shù)組就是字符數(shù)組
指針數(shù)組 - 存放指針的數(shù)組就是指針數(shù)組
int*
整型指針的數(shù)組
char*
字符指針的數(shù)組
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
int main() { int arr[10]; char ch[5]; int * parr[5]; char * pc[6]; return 0; } int main() { int a = 10; int b = 20; int c = 30; int * parr[3] = { &a,&b,&c }; for ( int i = 0;i < 3;i++) { printf ( "%d " , *(parr[i])); } return 0; } |
到此這篇關(guān)于C語言中的指針 初階的文章就介紹到這了,更多相關(guān)C語言中的指針內(nèi)容請搜索服務(wù)器之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持服務(wù)器之家!
原文鏈接:https://blog.csdn.net/weixin_49215278/article/details/120633039