1. 指標
地址,空間
大部分數字計算機將記憶體,分割為一個個空間,每一個空間大小為一個位元組
每一個位元組,都對應著一個編號進行管理,這些編號也稱為地址
什麼是指標,指標變數
C語言通常稱為低階語言,這裡的低階是指C語言與計算機底層有緊密的聯絡,可以透過指標來訪問記憶體空間
所以,指標可以理解為地址
既然指標就是地址,那麼指標變數就是儲存地址的變數
口語中的指標,實際上是指標變數
指標的申明
int * pa
* 表示pa是一個指標,
int, 表示指標的型別為整形, 儲存的是一個整形變數的地址,也叫做指向整形的指標
取地址& ,間接引用* 運算子
直接看一個例子
#include <stdio.h>
int main()
{
int a = 1;
int* pa = &a;
*pa = 2;
printf("%d", a);
}
執行流程
1,int a = 1
開闢4個位元組的空間,然後將1存進去
2,int* pa = &a
&, 取地址運算子
&a表示取出整形變數a的起始地址,存入整形指標pa的儲存空間中
3, *pa = 2
* ,間接定址運算子,透過地址訪問對應的空間
pa 儲存的是a的地址, *pa 實際上訪問的是a的空間,然後將存入2
2. 指標型別
指標的大小
#include <stdio.h>
int main()
{
printf("%d\n", sizeof(char*));
printf("%d\n", sizeof(int*));
printf("%d\n", sizeof(double*));
}
指標是儲存地址的變數,地址的大小由機器地址線決定
所以指標的大小都是一樣的,和型別無關
那麼,指標型別的意義是什麼 ?
型別的意義
1. 型別決定,*定址的許可權
觀察下面兩個例子
#include <stdio.h>
int main()
{
int a = 0x11223344;
int* pa = &a;
*pa = 0;
}
#include <stdio.h>
int main()
{
int a = 0x11223344;
char* pa = (char*)&a;
*pa = 0;
}
當pa的型別為整形時,*定址可以一次性訪問4個位元組
pa型別為字元時, 只能訪問一個位元組
2. 型別決定,指標的步長
#include <stdio.h>
int main()
{
int a = 0x11223344;
int* pa = &a;
char* pb = (char*)&a;
printf("%p\n", pa);
printf("int*: %p\n", pa + 1);
printf("char*: %p\n", pb + 1);
}
pa, 整形指標, +1跳過了4個位元組
pb, 字元指標, +1跳過了1個位元組
型別決定指標進行運算時,具體跳過多少個位元組
3. 指標運算
指標 + 整數
#include <stdio.h>
int main()
{
int a = 0;
int* pa = &a;
char* pb = (char*)&a;
printf("%p\n", pa);
printf("%p\n", pa+1);
printf("%p\n", pb);
printf("%p\n", pb + 1);
}
從中可以發現,指標+整數,是向高地址移動的,指標的步長由指標的型別決定
指標 - 整數
#include <stdio.h>
int main()
{
int a = 0;
int* pa = &a;
char* pb = (char*)&a;
printf("%p\n", pa);
printf("%p\n", pa - 1);
printf("%p\n", pb);
printf("%p\n", pb - 1);
}
指標-整數時,指標向低地址移動,移動的步長由型別決定
指標 - 指標
#include <stdio.h>
int main()
{
int arr[10] = {0,1,2,3,4,5,6,7,8,9};
printf("%d\n", &arr[9] - &arr[0]);
}
指標 - 指標,得到的是兩個指標之間的元素個數
分析
注意:
C語言規定,指標 - 指標時,必須要確保兩個指標指向同一記憶體塊
同時,保證兩個指標型別相同
指標 - 指標的應用
// 求字串長度
#include <stdio.h>
int len1(char* str)
{
int count = 0;
char* ps = str;
while (*str != '\0')
{
str++;
}
return str - ps; // 指標 - 指標
}
int main()
{
char arr[] = "abcdef";
int res = len1(arr);
printf("%d\n", res);
return 0;
}
指標的關係運算
可以用關係運算子,對兩個指標進行比較
比較的結構,取決於兩個指標在同一記憶體塊中的地址
#include <stdio.h>
int main()
{
int arr[10] = { 0,1,2,3,4,5,6,7,8,9 };
printf("%d\n", &arr[9] <= &arr[0]);
printf("%d\n", &arr[9] >= &arr[0]);
}
陣列元素9的地址大於或等於元素0 的地址,為1(真)
所以,兩個指標之間進行比較,實際上比較的是地址
4. 二級指標
什麼是二級指標
指標是一個儲存地址的變數,既然是一個變數,那麼就可以用&取地址運算子,取出一個變數的地址
所以,二級指標就是儲存一個一級指標地址的變數,也叫做指向指標的指標
#include <stdio.h>
int main()
{
int a = 0;
int* pa = &a; // 一級指標
int* *ppa = &pa; // 二級指標
}
二級指標的宣告與賦值
int* *ppa;
ppa前面的*, 表示pppa是一個指標變數,用來儲存地址
int*, 表示變數ppa儲存的是一個一級整形指標的地址
int* *ppa = &pa;
二級指標和一級指標一樣,可以用 =賦值運算子,進行賦值
二級指標的使用
#include <stdio.h>
int main()
{
int a = 0;
int* pa = &a; // 一級指標
int** ppa = &pa; // 二級指標
**ppa = 1;
printf("%d\n", a);
}
* *ppa = 1
*ppa,表示訪問ppa的空間, ppa存放的是pa的地址, 所以可以這麼理解 **ppa = *(pa)
*pa, 訪問的是a的空間,並存入1