1.指針基礎知識
? ? ? ? 1.1 指針變量的定義和使用
- ? ? ?指針也是一種數據類型,指針變量也是一種變量
- ? ? ?指針變量指向誰,就把誰的地址賦值給指針變量
#include<stdio.h>int main()
{int a = 0;char b = 100;printf("%p,%p \n", &a,&b); // 打印a,b的地址// int*代表的是一種數據類型,int*指針類型,p為變量名。// 定義了一個指針類型的變量,可以指向一個int類型變量的地址int *p;p = &a; // 將a的地址賦值給變量p,p也是一個變量,值為內存編號printf("%d\n", *p); char *p1 = &b;printf("%c \n", *p1);return 0;
}
1.2通過指針間接修改變量的值
#include<stdio.h>// 通過指針間接改變變量的值int main()
{int a = 0;int b = 11;int *p = &a;*p = 100;printf("a = %d, *p = %d \n", a,*p);p = &b;*p = 22;printf("b = %d, *p = %d \n", b,*p);return 0;
}
1.3指針的大小
- ?使用sizeof()測量指針的大小,得到的總是4和8
- ?sizeof()測的是指針變量指向存儲地址的大小
- ?在32 位平臺,所有的指針(地址)都是 32 位(4 字節)?
- ?在64 位平臺,所有的指針(地址)都是 64 位(8 字節)
1.4 野指針和空指針
? ? ? ? ?指針變量也是變量,是變量就可以任意賦值,不要越界即可(32 位為 4 字 節,64 位為 8 字節),但是,任意數值賦值給指針變量沒有意義,因為這樣 的指針就成了野指針,此指針指向的區域是未知(操作系統不允許操作此指針 指向的內存區域)。所以,野指針不會直接引發錯誤,操作野指針指向的內存 區域才會出問題。
#include<stdio.h>int main()
{// 野指針 ---1.沒有一個有效的地址空間的指針int *p;*p = 1000;// 2. p變量有一個值,但該值不是可訪問的內存區域int *p = 10; // 0-255留給操作系統*p = 2000;return 0;
}
? ? ? ? ?但是,野指針和有效指針變量保存的都是數值,為了標志此指針變量沒有指向 任何變量(空閑可用),C 語言中,可以把 NULL 賦值給此指針,這樣就標志此 指針為空指針,沒有任何指針。
1.5萬能指針void
? ? ? ? ? ?void *指針可以指向任意變量的內存空間:
#include<stdio.h>int main()
{// void * 指針int a = 345;void *p;p = &a;printf("%d\n", *(int*)p); // 進行強制類型轉換return 0;
}
1.6const修飾指針
2.指針和數組
? ? ? ?2.1數組名
? ? ? ? ? ?數組名字是數組的首元素地址,但它是一個常量-----不可以被修改和賦值
? ? ? ?2.2 指針操作數組元素
#include<stdio.h>int main()
{int a[]= {1,2,4,5,6,7,8,9,0};int n = sizeof(a) / sizeof(a[0]);for (size_t i = 0; i < n; i++){printf("%d", a[i]);}// 定義1個指針變量保存數組a的地址int *p = a;for(int i = 0; i < n; i++){p[i] = 2 * i;}for(int i = 0; i < n; i++){printf("%d", *(p+i));}return 0;
}
2.3指針加減運算
1)加法運算
- ?指針計算不是簡單的整數相加
- ?如果是一個 int *,+1 的結果是增加一個 int 的大小
- ?如果是一個 char *,+1 的結果是增加一個 char 大小
通過改變指針指向操作數組元素
#include<stdio.h>int main()
{int arr[] = {1,2,3,4,5,6,7,8,9};int i = 0;int n = sizeof(arr) / sizeof(arr[0]);int *p = arr;for(int i = 0; i < n; i++){printf("%d \n", *p);p++;}return 0;
}
2) 減法運算
#include <stdio.h>int main(){int a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };int i = 0;int n = sizeof(a) / sizeof(a[0]);int *p = a+n-1; /// 指向數組的最后一個元素進行倒序排列for (i = 0; i < n; i++){printf("%d, ", *p);p--;}printf("\n");return 0;}
&數組名+1:------相當于加一個數組
3)指針加減指針:
指針加指針:error
指針-指針:對于數組來說:偏移過的元素個數
#include <stdio.h>int main() {int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};int *p2 = &a[5]; // 獲取第3個元素(值為3)的地址int *p1 = &a[3]; // 獲取第2個元素(值為2)的地址printf("p1 = %p, p2 = %p\n", p1, p2);int n1 = p2 - p1; // 指針相減,結果是元素個數差(2)printf("n1 = %d\n", n1);return 0;
}
3.指針實現的strlen函數
#include<stdio.h>#include<string.h>int mystrlen(char str[])
{int i = 0;while(str[i] != '\0'){i++;}return i;
}int main()
{char str[] = "hello";int ret = mystrlen(str);printf("ret = %d \n", ret);return 0;
}
4.指針的比較運算
#include<stdio.h>int main()
{int a[] = {1,2,4,5,6,7,8,9,0};int *p = &a[3];if(p>a){printf("成立\n");}else if(p<a){printf("不成立\n");}else{printf("==\n");}return 0;
}
對于普通變量來說比較語法允許無實際意義
對于數組來說:地址之間可以比較大小得出元素存儲前的先后順序
5.指針數組
指針數組,它是數組,數組的每個元素都是指針類型。本質上是一個二級指針
#include<stdio.h>// 指針數組1int main()
{int a = 10;int b = 20;int c = 30;int *p1 = &a;int *p2 = &b;int *p3 = &c;int *arr[] = {p1,p2,p3}; // 整形指針數組arr,存的都是整形地址printf("*(arr[0]) = %d\n",*(*(arr+0)));printf("*(arr[0]) = %d\n",*(arr[0]));printf("*(arr[0]) = %d\n",**arr); /// 二級指針// 指針數組2int a[] = {10};int b[] = {20};int c[] = {30};int *arr[] = {a,b,c};arr[0][0] = *(*(arr+0)+0); ///等價于 ==**arrreturn 0;
}
6.多級指針
- ?C 語言允許有多級指針存在,在實際的程序中一級指針最常用,其次是二 級指針。
- 二級指針就是指向一個一級指針變量地址的指針。
- ?三級指針基本用不著,但考試會考。
#include<stdio.h>int main()
{int a = 10;int *p = &a;int **pp = &p;int ***ppp = &pp;printf("***ppp = %d \n", ***ppp);printf("**pp = %d \n", **pp);printf("*p = %d \n", *p);printf("a = %d \n",a);return 0;
}