網(wǎng)站建設正版軟件廣東網(wǎng)站營銷seo方案
文章目錄
- 1.指針是什么
- 2.指針和指針類型
- 2.1 指針的解引用
- 2.2 指針+ -整數(shù)
- 3.野指針
- 3.1 野指針成因
- 3.2 如何規(guī)避野指針
- 4. 指針運算
- 4.1 指針+-整數(shù)
- 4.2 指針-指針
- 4.3 指針的關系運算
- 5. 指針和數(shù)組
- 6. 二級指針
- 7. 指針數(shù)組
1.指針是什么
指針理解的2個要點:
- 指針是內存中一個最小單元的編號,也就是地址
- 平時口語中說的指針,通常指的是指針變量,是用來存放內存地址的變量
總結: 指針就是地址,口語中說的指針通常指的是指針變量。
我們可以這樣理解:
內存:
指針變量
我們可以通過&(取地址操作符)取出變量的內存其實地址,把地址可以存放到一個變量中,這個變量就是指針變量
看代碼:
#include <stdio.h>
int main()
{int a = 10;//在內存中開辟一塊空間int* p = &a;//這里我們對變量a,取出它的地址,可以使用&操作符。//a變量占用4個字節(jié)的空間,這里是將a的4個字節(jié)的第一個字節(jié)的地址存放在p變量中,p就是一個之指針變量。return 0;
}
總結:
指針變量,用來存放地址的變量。(存放在指針中的值都被當成地址處理)。
經(jīng)過仔細的計算和權衡我們發(fā)現(xiàn)一個字節(jié)給一個對應的地址是比較合適的。
對于32位的機器,假設有32根地址線,那么假設每根地址線在尋址的時候產(chǎn)生高電平(高電壓)和低電平(低電壓)就是(1或者0);
那么32根地址線產(chǎn)生的地址就會是:
這里我們就明白:
- 在32位的機器上,地址是32個0或者1組成二進制序列,那地址就得用4個字節(jié)的空間來存儲,所以一個指針變量的大小就應該是4個字節(jié)。
- 那如果在64位機器上,如果有64個地址線,那一個指針變量的大小是8個字節(jié),才能存放一個地址。
總結:
- 指針變量是用來存放地址的,地址是唯一標示一個內存單元的
- 指針的大小在32位平臺是4個字節(jié),在64位平臺是8個字節(jié)
2.指針和指針類型
char *pc = NULL;
int *pi = NULL;
short *ps = NULL;
long *pl = NULL;
float *pf = NULL;
double *pd = NULL;
指針的定義方式是: type + * 。
char* 類型的指針是為了存放 char 類型變量的地址。
short* 類型的指針是為了存放 short 類型變量的地址。
int* 類型的指針是為了存放 int 類型變量的地址。
2.1 指針的解引用
代碼演示
#include <stdio.h>
int main()
{int n = 0x11223344;char* pc = (char*)&n;int* pi = &n;*pc = 0; //重點在調試的過程中觀察內存的變化。*pi = 0; //重點在調試的過程中觀察內存的變化。return 0;
}
總結:
指針的類型決定了,對指針解引用的時候有多大的權限(能操作幾個字節(jié))。
比如: char* 的指針解引用就只能訪問一個字節(jié),而 int* 的指針的解引用就能訪問四個字節(jié)。
2.2 指針+ -整數(shù)
代碼演示
#include <stdio.h>
int main()
{int n = 10;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;
}
運行結果:
總結: 指針的類型決定了指針向前或者向后走一步有多大(距離)。
3.野指針
概念: 野指針就是指針指向的位置是不可知的(隨機的、不正確的、沒有明確限制的)
3.1 野指針成因
- 指針未初始化
#include <stdio.h>
int main()
{int* p;//局部變量指針未初始化,默認為隨機值*p = 20;return 0;
}
代碼運行之后會報錯
- 指針越界訪問
#include <stdio.h>
int main()
{int arr[10] = { 0 };int* p = arr;int i = 0;for (i = 0; i <= 11; i++){//當指針指向的范圍超出數(shù)組arr的范圍時,p就是野指針*(p++) = i;}return 0;
}
- 指針指向的空間釋放
#include <stdio.h>
int* test()
{int a = 10;return &a;
}
int main()
{int*p = test();*p = 100;return 0;
}
a出test函數(shù)就已經(jīng)銷毀,但是return把a的地址傳給了p,p里邊存放了a的地址,但是p不能在對其進行修改
3.2 如何規(guī)避野指針
- 指針初始化
- 小心指針越界
- 指針指向空間釋放,及時置NULL
- 避免返回局部變量的地址
- 指針使用之前檢查有效性
#include <stdio.h>
int main()
{//一個指針不知道應該指向哪里的時候,暫時可以初始化為NULL;int* p = NULL;if (p != NULL)//判斷指針是否為空,不為空再進行訪問{*p = 100;}return 0;
}
4. 指針運算
4.1 指針±整數(shù)
代碼演示:
#include <stdio.h>int my_strlen(char * str)
{int count = 0;while (*str != '\0'){count++;//指針+整數(shù)str = str + 1;}return count;
}int main()
{int len = my_strlen("abcdef");printf("%d\n", len);return 0;
}
運行結果
4.2 指針-指針
指針-指針=地址-地址
代碼演示:
#include <stdio.h>
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };int n = &arr[9] - &arr[0];printf("%d\n", n);return 0;
}
運行結果:
總結: 指針加整數(shù)等于指針,指針減指針等于整數(shù)
4.3 指針的關系運算
//代碼一
#define N_VALUES 5
float values[N_VALUES];
float* vp;
//指針關系的運算
for (vp = &values[N_VALUES]; vp > &values[0];)
{*--vp = 0;
}
通過- -vp把values數(shù)組改成0
代碼簡化
//代碼二:
for(vp = &values[N_VALUES-1]; vp >= &values[0];vp--)
{*vp = 0;
}
讓vp指向下標為4的元素,通過- -vp把values數(shù)組改成0
代碼二實際在絕大部分的編譯器上是可以順利完成任務的,然而我們還是應該避免這樣寫,因為標準并不保證
它可行。
標準規(guī)定:
允許指向數(shù)組元素的指針與指向數(shù)組最后一個元素后面的那個內存位置的指針比較,但是不允許與
指向第一個元素之前的那個內存位置的指針進行比較。
允許p1與p3進行比較,不允許p1與p2進行比較
5. 指針和數(shù)組
指針就是指針,不是數(shù)組
數(shù)組就是數(shù)組,也不是指針
指針和數(shù)組的關系:
指針是可以指向數(shù)組元素的
因為指針可以運算,所以借助指針可以訪問數(shù)組
代碼演示:
#include <stdio.h>
int main()
{int arr[10] = { 0 };int* p = arr;//指針存放數(shù)組首元素的地址int i = 0;//存放for (i = 0; i < 10; i++){*p = i + 1;p++;}//打印p = arr;for (i = 0; i < 10; i++){printf("%d ", *(p + i));}return 0;
}
運行結果:
6. 二級指針
指針變量也是變量,是變量就有地址,那指針變量的地址存放在哪里?
這就是 二級指針 。
代碼演示:
#include <stdio.h>
int main()
{int a = 10;//a是要在內存中申請4個字節(jié)的空間的//一級指針int* pa = &a;//0x0012ff40, pa是指針變量,用來存放地址,也得向內存申請,申請4/8//二級指針int** ppa = &pa;//0x0012ff48printf("%d\n", **ppa);return 0;
}
運行結果:
二級指針的運算
- *ppa 通過對ppa中的地址進行解引用,這樣找到的是 pa , *ppa 其實訪問的就是 pa。
int b = 20;
*ppa = &b;//等價于 pa = &b;
- **ppa 先通過 *ppa 找到 pa ,然后對 pa 進行解引用操作: *pa ,那找到的是 a。
**ppa = 30;
//等價于*pa = 30;
//等價于a = 30;
7. 指針數(shù)組
指針數(shù)組是指針還是數(shù)組?
答案:是數(shù)組。是存放指針的數(shù)組。
代碼演示:
#include <stdio.h>
int main()
{int a = 10;int b = 20;int c = 30;int* arr[] = { &a,&b,&c };int i = 0;for (i = 0; i < 3; i++){printf("%d ", *(arr[i]));}return 0;
}
運行結果:
指針數(shù)組與二級指針的結合
#include <stdio.h>
int main()
{char* arr[5];//[char* char* char* char* char*]char** p = arr;//&arr[0] - char**return 0;
}
用一維數(shù)組模擬出一個二維數(shù)組
看代碼:
#include <stdio.h>
int main()
{int arr1[] = { 1,2,3,4,5 };int arr2[] = { 2,3,4,5,6 };int arr3[] = { 3,4,5,6,7 };int* ptr[] = { arr1,arr2,arr3 };int i = 0;for (i = 0; i < 3; i++){int j = 0;for (j = 0; j< 5; j++){printf("%d ",ptr[i][j]);}printf("\n");}return 0;
}
運行結果: