準備
博主:大大怪先森(記得關注哦!)
編程環境:vs2013
提示:基于C語言所寫的關于指標的內容,小白也能看懂!!!
文章目錄
- 準備
- 前言
- 一、指標是什么?
- 二、指標和指標型別
- 1.指標型別
- 2.指標型別的解參考
- 3.野指標
- 3.1.野指標的成因
- 3.2.如何規避野指標
- 三、指標陣列
- 四、陣列指標
- 1.陣列指標的定義
- 2.陣列指標的使用
- 五、指標的傳參
- 1.一維陣列傳參
- 2.二維陣列傳參
- 3.一級指標傳參
- 4.二級指標傳參
- 六、函式指標
- 七、函式指標陣列
- 八、回呼函式
- 結語
前言
C語言指標的問題,是否是最讓我們頭暈眼花???
無限的套娃行為,成為我們懼怕c語言的首要障礙,各位小可愛不要擔心,
博主大大已經為各位準備好了學習程序中可能遇到的問題!讓我們一起揭開指標的全貌吧!!!!
提示:以下是本篇文章正文內容,內容原創,著作權必究!!!</fO
一、指標是什么?
指標:
在計算機科學中,指標(Pointer)是編程語言中的一個物件,利用地址,它的值直接指向(points to)存在電腦存盤器中另一個地方的值,由于通過地址能找到所需的變數單元,可以說,地址指向該變數單元,因此,將地址形象化的稱為“指標”,意思是通過它能找到以它為地址的記憶體單元,
除此之外大多數的程式猿的理解即是:指標 = 地址
小結:
指標是用來存放地址的,地址是唯一標示一塊地址空間的,
指標的大小在32位平臺是4個位元組,在64位平臺是8個位元組,
二、指標和指標型別
1.指標型別
我們都知道,變數有不同的型別,整形,浮點型等,那指標有沒有型別呢?
將&num(變數num的地址)保存到p指標中,我們知道p就是一個指標變數,那它的型別是怎樣的呢?
int main()
{
int a = 0;
char ch = 0;
float p = 0.0f;
int* ptr = &a; //整形指標
char* ptr = &ch;//字符指標
float* ptc = &p;//單精度浮點數指標
//...
return 0;
}
小結:我們不難看出存放字符變數的地址就是字符指標,存放整形變數的地址的就是整形指標
2.指標型別的解參考
int main()
{
int a = 10;
int* pa = &a;
char* pc = &a;
printf("%p\n", pa);
printf("%p\n", pc);
printf("%p\n", pa+2);
printf("%p\n", pc+2);
//指標型別的意義2:
//指標型別決定了,指標+-整數的時候的步長(指標+-整數的時候,跳過幾個位元組)
//int* 指標 +1 跳過4個位元組
//char* 指標+1 跳過1個位元組
//int a = 0x11223344;
//char* pc = &a;//int*
//*pc = 0;
//int*pa = &a;
//*pa = 0;
//指標型別的意義1:
//指標型別決定了指標解參考操作的時候,一次訪問幾個位元組(訪問記憶體的大小)
//char* 指標解參考訪問1個位元組
//int* 指標解參考訪問4個位元組
return 0;
}
小結:指標的型別決定了,對指標解參考的時候有多大的權限(能操作幾個位元組),
比如: char* 的指標解參考就只能訪問一個位元組,而 int* 的指標的解參考就能訪問四個位元組,
3.野指標
3.1.野指標的成因
- 指標未初始化
int main()
{
int* p;//區域變數為初始化默認為隨機值
*p = 20;
return 0;
}
- .指標越界訪問
int main()
{
int arr[10] = {0};
int *p = arr;
int i = 0;
for(i=0; i<=11; i++)
{
//當指標指向的范圍超出陣列arr的范圍時,p就是野指標
*(p++) = i;
}
return 0; }
3.指標指向的空間記憶體未釋放
詳細講解:請觀看博主大大的另一篇文章《動態記憶體管理》
為了防止小可愛們下次走丟了,趕緊…

3.2.如何規避野指標
我們到底應該怎么規避這些問題?
各位小可愛在運用指標的時候一定要注意一下幾點
- 指標初始化
- 小心指標越界
- 指標指向空間釋放即使置NULL
- 避免回傳區域變數的地址
- 指標使用之前檢查有效性
所以說一個優秀的程式猿代碼規范非常重要!!!!
在此給各位小可愛推薦一本書《高質量的c/c++編程》,小編不是在此打廣告哦,

靜下心好好看一看,我相信各位小可愛一定會受益匪淺!!!
三、指標陣列
指標陣列是指標還是陣列?
答案:是陣列,是存放指標的陣列,
陣列我們已經知道整形陣列,字符陣列,

int main()
{
int a = 10;
int b = 20;
int c = 30;
int* arr[3] = {&a, &b, &c};
int i = 0;
for (i = 0; i < 3; i++)
{
printf("%d\n", *(arr[i]));
}
//int* pa = &a;
//int* pb = &b;
//int* pc = &c;
return 0;
}
四、陣列指標
1.陣列指標的定義
陣列指標是指標?還是陣列?
答案是:指標,
我們已經熟悉整形指標,浮點數指標,那么陣列指標就是指向陣列的指標
int* pa[10];
int (*pb)[10];
到底哪一個是陣列指標呢?
答案是:int (*pb)[10]
解釋:pb先和*結合,說明pb是一個指標變數,然后指著指向的是一個大小為10個整型的陣列,
所以p是一個指標,指向一個陣列,叫陣列指標,
這里要注意:[]的優先級要高于星號*號的,所以必須加上()來保證pb先和*相結合
2.陣列指標的使用
代碼如下(示例):
//void print1(int arr[], int sz)
//{
// int i = 0;
// for (i = 0; i < sz; i++)
// {
// printf("%d ", arr[i]);
// }
//}
//void print2(int* arr, int sz)
//{
// int i = 0;
// for (i = 0; i < sz; i++)
// {
// printf("%d ", *(arr + i));
// }
//}
//陣列指標
//void print3(int (*parr)[10], int sz)//這是一個錯誤的示范
//{
// int i = 0;
// for (i = 0; i < sz; i++)
// {
// printf("%d ", parr[i]);//parr[i] == *(parr+i)
// }
//}
void print4(int(*pa)[10], int sz)
{
int i = 0;
for (i = 0; i < sz - 1; i++)
{
//printf("%d ", *(pa + i));//錯誤
//printf("%d ", pa[i]);//erro
printf("%d ", (*pa)[i]);//*(pa +0)[i] == pa[0][i] == *(*(pa) + i)
printf("%d ", pa[0][i]);
printf("%d ", *(*(pa)+i));
}
}
int main()
{
int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int sz = sizeof(arr) / sizeof(arr[0]);
print4(&arr, sz);
//print3(&arr, sz);
//print2(arr, sz);
//print1(arr, sz);//列印arr陣列的內容
return 0;
}
學習了陣列指標你是否對數值指標有更加深刻的理解了~~~
各位下可愛再看看下面的代碼的意思吧!
int arr[10];
int* arr2[10];
int (*pa)[10];
int* (*pa[10])(10);

五、指標的傳參
1.一維陣列傳參
思考如下代碼(示例):
#include <stdio.h>
void test(int arr[])//ok?
{}
void test(int arr[10])//ok?
{}
void test(int *arr)//ok?
{}
void test2(int *arr[20])//ok?
{}
void test2(int **arr)//ok?
{}
int main()
{
int arr[10] = {0};
int *arr2[20] = {0};
test(arr);
test2(arr2);
1.× 2.√ 3.√ 4.× 5.√
2.二維陣列傳參
代碼如下(示例):
void print2( int(*p)[5], int r, int c)
{
int i = 0;
for (i = 0; i < r; i++)
{
int j = 0;
for (j = 0; j < c; j++)
{
//printf("%d ", *(*(p + i) + j));
printf("%d ", p[i][j]);
}
printf("\n");
}
}
int main()
{
int arr[3][5] = { 1,2,3,4,5, 2,3,4,5,6,3,4,5,6,7 };
//二維陣列傳參
//print1(arr, 3, 5);
print2(arr, 3, 5);//arr 是陣列名,陣列名是首元素地址
return 0;
}
小結:二維陣列傳參arr是相當于第一個行的陣列名

其他接收引數:int* arr or int** arr or int arr[3][5]
3.一級指標傳參
代碼如下(示例):
#include <stdio.h>
void print(int *p, int sz)
{
int i = 0;
for(i=0; i<sz; i++)
{
printf("%d\n", *(p+i));
}
}
int main()
{
int arr[10] = {1,2,3,4,5,6,7,8,9};
int *p = arr;
int sz = sizeof(arr)/sizeof(arr[0]);
//一級指標p,傳給函式
print(p, sz);
return 0;
}
當一個函式的引數部分為一級指標的時候,函式能接收什么引數?
in* p or in** pa or int arr[10];
4.二級指標傳參
void test(char **p)
{}
int main()
{
char c = 'b';
char*pc = &c;
char**ppc = &pc;
char* arr[10];
test(&pc);
test(ppc);
test(arr);//Ok?
return 0; }
√
六、函式指標
代碼如下(示例):
#include <stdio.h>
void test()
{
printf("hehe\n");
}
int main()
{
printf("%p\n", test);
printf("%p\n", &test);
return 0;
}
輸出結果:

思考:兩者的地址相同,那如何吧地址存放在指標當中?
答案:void (*fun)(int,int)
這就是所謂的函式指標 ,fun是變數名,void (*)(int,int)則是變數的型別,表示fun指向的函式的兩個引數分別都是int型別,
七、函式指標陣列
陣列是一個存放相同型別資料的存盤空間,那我們已經學習了指標陣列,
比如:
int *arr[10];
陣列的每個元素是int*
那么那要把函式的地址存到一個陣列中,那這個陣列就叫函式指標陣列,
那函式指標的陣列如何定義呢?
int (*pa)(int,int)
int (*pa[10])(int,int)
[]的優先級高于高于解參考的星號所以int (*pa[10])(int,int)的本質上是一個陣列,而每一個陣列的元素存放的都是一個函式的地址即函式指標,每個函式指標所指向的都是含有兩個int型別的引數
小練習:使用函式指標陣列實作的簡易計算機
#include <stdio.h>
int add(int a, int b)
{
return a + b;
}
int sub(int a, int b)
{
return a - b;
}
int mul(int a, int b)
{
return a*b;
}
int div(int a, int b)
{
return a / b;
}
int main()
{
int x, y;
int input = 1;
int ret = 0;
int(*p[5])(int x, int y) = { 0, add, sub, mul, div }; //轉移表
while (input)
{
printf("*************************\n");
printf(" 1:add 2:sub \n");
printf(" 3:mul 4:div \n");
printf("*************************\n");
printf("請選擇:");
scanf("%d", &input);
if ((input <= 4 && input >= 1))
{
printf("輸入運算元:");
scanf("%d %d", &x, &y);
ret = (*p[input])(x, y);
}
else
printf("輸入有誤\n");
printf("ret = %d\n", ret);
}
return 0;
}
八、回呼函式
回呼函式就是一個通過函式指標呼叫的函式,如果你把函式的指標(地址)作為引數傳遞給另一
個函式,當這個指標被用來呼叫其所指向的函式時,我們就說這是回呼函式,回呼函式不是由該
函式的實作方直接呼叫,而是在特定的事件或條件發生時由另外的一方呼叫的,用于對該事件或
條件進行回應,
詳細了解:請關于博主的下一篇文章《指標和陣列筆試題》
結語
希望本篇文章能給各位帶來幫助,如有不足還請指正!!!
碼字不易,各位大大給個收藏點贊吧!!!

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/303981.html
標籤:其他
