目錄
一. 指針是什麼?
二. 指針和指針類型
三. 野指針
四. 指針運算
五. 指針和數組
六. 二級指針
七. 指針數組
總結
前言
本篇部落客要是初始指針,簡單使用指針,在日常的使用解決問題中運用指針。
提示:以下是本篇文章正文内容
一. 指針是什麼?
指針:是記憶體單元的編号,也就是位址。
指針了解的2個要點:
1. 指針是記憶體中一個最小單元的編号,也就是位址
2. 平時口語中說的指針,通常指的是指針變量,是用來存放記憶體位址的變量
總結:指針就是位址,口語中說的指針通常指的是指針變量。
是以我們可以了解為:記憶體
記憶體單元 - 編号 - 位址 - 指針
平時口語中的指針是指針變量,是存放記憶體變量的
記憶體被劃分為一個個小的記憶體單元 一個基本的記憶體單元的大小是一個位元組
位址: 記憶體單元的編号 0X00000000
記憶體單元編号的産生: 32位機器-32跟位址線-實體的電線- 通電-1/0
00000000 00000000 00000000 00000000 -- 4個位元組
00000000 00000000 00000000 00000001
00000000 00000000 00000000 00000010
.... ... ... ...
11111111 11111111 11111111 11111111
2*10^32 bite -- 4GB
64位
指針變量
我們可以通過&(取位址操作符)取出變量的記憶體其實位址,把位址可以存放到一個變量中,這個
變量就是指針變量
int main()
{
int a = 10;// 四個位元組
int* pa = &a;//pa存的是位址 是以pa就是指針變量
printf("%d\n", sizeof(pa));
printf("%p", &a);
return 0;
}
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiZpdmL4ATY4YmZjhTYyY2MmJTN4cjMxUGO3MzNjdTOmJjN0IDZmJzM2I2LcVDMyIDMy8CXzV2Zh1WavwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.gif)
下面這張圖可便于大家了解:
舉例:
int main()
{
int a = 0x11223344;
int* pa = &a;
*pa = 0;
//char* pc = &a;
//*pc = 0;
//int* --> 4
//char* --> 1
//double* --> 8
return 0;
}
位址的列印:
二. 指針和指針類型
這裡我們在讨論一下:指針的類型
我們都知道,變量有不同的類型,整形,浮點型等。那指針有沒有類型呢?
準确的說:有的。
int main()
{
int a = 10;
int* pa = &a;//整形 --4
char* pc = &a;//字元 --1
printf("%p\n", pa);
printf("%p\n", pa+1);
printf("%p\n", pc);
printf("%p\n", pc+1);
//指針類型決定了指針向前或者向後走一步走的距離 -- 機關是位元組
return 0;
}
指針類型決定了指針向前或者向後走一步走的距離 -- 機關是位元組
指針的定義方式是: type + * 。
其實:
char* 類型的指針是為了存放 char 類型變量的位址。
short* 類型的指針是為了存放 short 類型變量的位址。
int* 類型的指針是為了存放 int 類型變量的位址。
2.1 指針的解引用
總結:
指針的類型決定了,對指針解引用的時候有多大的權限(能操作幾個位元組)。
比如: char* 的指針解引用就隻能通路一個位元組,而 int* 的指針的解引用就能通路四個位元組。
2.2 指針+-整數
總結:指針的類型決定了指針向前或者向後走一步有多大(距離)
舉例:
分析:
int main()
{
int arr[10] = { 0 };
int* p = arr;
int i = 0;
for (i = 0; i < 10; i++)
{
//正着初始化
*(p+i) = i+1;
}
//正着列印
int* m = &arr[0];
for (i = 0; i < 10; i++)
{
printf("%d ", *m);
m++;
}
printf("\n");
//倒着列印 9 8 7 ...
int* q = &arr[9];
for (i = 0; i < 10; i++)
{
printf("%d ", *q);
q--;
}
return 0;
}
示範分析:
三. 野指針
概念: 野指針就是指針指向的位置是不可知的(随機的、不正确的、沒有明确限制的)
3.1 野指針成因
1. 指針未初始化
int main()
{
int* p;//局部變量指針未初始化,預設為随機值
*p = 20;
return 0;
}
2. 指針越界通路
int arr[10] = { 0 };
int* p = arr;
for (int i = 0; i <= 10; i++)
{
*p = i;
p++;
}
3. 指針指向的空間釋放
//指針指向的空間釋放
int* test()
{
int a = 100;
return &a;
}
int main()
{
int* p = test();
printf("%d", *p);
return 0;
}
int main()
{
int a = 10;
int* pa = &a;// 知道存給誰
int* p = NULL;//初始化成空指針
if (p != NULL)
{
}
return 0;
}
分析:
3.2 如何規避野指針
四. 指針運算
4.1 指針+-整數
初始化并指派列印
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+1;
}
//列印
for (i = 0; i < sz; i++)
{
printf("%d ", *(p + i));
}
return 0;
}
4.2 指針-指針
int main()
{
/*int a[10] = { 0 };
printf("%d\n", &a[9] - &a[0]);
printf("%d\n", &a[0] - &a[9]);*/
int a = 10;
char c = 'w';
return 0;
}
分析:
舉例2:求字元串的長度
在之前我們用strlen函數寫了可以求字元串的長度
//求字元串長度的函數 strlen
#include <string.h>
int My_strlen(char* s)
{
int count = 0;
while(*s != '\0')
{
count++;
s++;
}
return count;
}
int main()
{
char arr[] = "abc";
int len =My_strlen(arr);
printf("%d\n", len);
return 0;
}
同樣我們也可以使用指針減指針的方法
int My_strlen(char* s)
{
char* start = s;
while (*s != '\0')
{
s++;
}
return s - start;
}
int main()
{
char arr[] = "abc";
int len =My_strlen(arr);
printf("%d\n", len);
return 0;
}
分析:
4.3 指針的關系運算
int main()
{
float a[5];
float* p;
for (p = &a[5]; p >= &a[0];)
{
*--p = 0;
}
return 0;
}
改進:
for (p = &a[4]; p >= &a[0]; p--)
{
*p = 0;
}
标準規定:
允許指向數組元素的指針與指向數組最後一個元素後面的那個記憶體位置的指針比較,但是不允許與
指向第一個元素之前的那個記憶體位置的指針進行比較。
五. 指針和數組
指針 -- 位址
數組 -- 一組相同類型的資料
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
//arr首元素位址
int* p = arr;
int i = 0;
for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
{
printf("%p == %p \n", p + i,&arr[i]);
}
return 0;
}
分析:
可見數組名和數組首元素的位址是一樣的。
結論:數組名表示的是數組首元素的位址。
那麼這樣寫代碼是可行的:
int arr[10] = {1,2,3,4,5,6,7,8,9,0};
int *p = arr;//p存放的是數組首元素的位址
既然可以把數組名當成位址存放到一個指針中,我們使用指針來通路一個就成為可能。
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,0 };
int* p = arr; //指針存放數組首元素的位址
int sz = sizeof(arr) / sizeof(arr[0]);
int i = 0;
for (i = 0; i < sz; i++)
{
printf("&arr[%d] = %p <====> p+%d = %p\n", i, &arr[i], i, p + i);
}
return 0;
}
是以 p+i 其實計算的是數組 arr 下标為i的位址
六. 二級指針
指針變量也是變量,是變量就有位址,那指針變量的位址存放在哪裡?
這就是 二級指針 。
int main()
{
int a = 10;
int* pa = &a;
int** ppa = &pa; //ppa就是一個二級指針
**ppa = 20;
printf("%d\n",a);
return 0;
}
七. 指針數組
指針數組是指針還是數組?
答案:是數組。是存放指針的數組。
數組我們已經知道整形數組,字元數組
int main()
{
int arr[10];//整形數組
char ch[5];//字元數組
//指針數組 --- 存放指針的數組
int a = 10;
int b = 20;
int c = 30;
int* arr2[5] = {&a,&b,&c};//存放整形指針的數組
int i = 0;
for (i = 0; i < 3; i++)
{
printf("%d ", *(arr2[i]));
}
return 0;
}