知識重復
-
變量指針:變量最小的地址值(首地址),本質是地址、指針
-
指針變量:存儲指針的變量,本質是變量
-
&:取地址運算符(取址符、取地址符),獲取變量、數組等的地址
-
*:指針操作符,如果這個符號前面有數據類型,就被稱為“指針聲明符”,如果沒有數據類型,就被稱為“解引用符”
-
指向:指針變量存儲了誰的地址,這個指針變量就指向了誰
-
交換指向:指向發生改變,指向對象的數據不會改變
-
交換數據:指向不發生改變,指向對象的數據會改變
-
指針變量本質上還是變量,只不過指針變量只能存儲其他內存單元的地址,我們借助于指針變量,就能實現內存空間的共享
-
共享他人空間:
int a = 10; int *p = &a; int *q = p;
-
共享自己的空間:
int a = 10; int *p = &a; //a和p共享a的空間
指針數組和數組指針
數組指針
定義
- 概念:數組指針是指向數組的指針(指針變量),本質上還是指針
指針變量指向數組元素和數組指針的區別:
特點
- ①先有數組,再有指針
- ②它指向的是一個完整的數組
一維數組指針
語法
數據類型 (*指針變量名)[容量];
案例
我們之前所學的是指向數組元素的指針,本質上是指針變量;現在我們學的是指向數組的指針,叫做數組指針
二維數組指針
語法:
數據類型 (*指針變量名)[行容量][列容量];
案例1
//寫法1:二維數組指針指向二維數組----不推薦
#include <stdio.h>
int main()
{//創建一個二維數組int arr[][3] = {10,20,30,100,200,300,1000,2000,3000};//定義一個二維數組指針指向二維數組int (*p)[][3] = &arr;//遍歷數組for(int i = 0;i < 3; i++){for(int j = 0;j < 3; j++){printf("%-6d",(*p)[i][j]);}}printf("\n");//寫法2:一維數組指針指向二維數組-----推薦//創建一個二維數組int arr[][3] = {10,20,30,100,200,300,1000,2000,3000}; //定義一個一維數組指針指向二維數組,相當于指針指向的是二維數組的行[行容量]int (*p)[3] = arr;//等價于&arr[0] (*p):指向數組的行 int arr[] = {100,200,300}; int *p = arr; 解引用p得到第一個元素//遍歷數組for(int i = 0;i < 3; i++){for(int j = 0;j < 3; j++){printf("%-6d",(*p)[i][j]);}}printf("\n"); return 0;
}
案例2
/*
**指向一維數組的指針
*/#include <stdio.h>int t_pl()
{//創建一個一維數組int arr[] = {10,20,30,40,50};//計算數組大小int len = sizeof(arr) / sizeof(arr[0]);//創建一個數組指針指向一維數組arrint (*p)[len] = &arr;//借助數組指針遍歷數組for(int i = 0; i < len; i++){//p 指向數組arr,p存儲了數組arr的地址,如果要通過指針訪問數組,就要對地址解引用(*p), *和[]在一起,[]的優先級大于*printf("%-4d", (*p)[i]);}printf("\n");
}/*
**指向二維數組的指針
*/int t_p2()
{//創建一個二維數組int arr[][3] = {{10,20,30},{100,2200,300},{1000,2000,3000}};//獲取行和列的容量int row_len = sizeof(arr) / sizeof(arr[0]);int col_len = sizeof(arr[0]) / sizeof(arr[0][0]);//方式1(不推薦) 二維數組指針指向二維數組int (*p)[][3] = &arr;//遍歷數組for(int i = 0;i < row_len; i++){for(int j = 0; j < col_len; j++){printf("%-6d", (*p)[i][j]); } }printf("\n");//方式2(推薦) 一維數組指針指向二維數組,本質上是一維數組指針指向二維數組的行(默認首行)//&arr:獲取該二維數組的地址,范圍作用于整個數組//arr:數組名,默認指向第一個元素,這個就是行,默認首行,范圍作用于整個行,等價于&arr[0]//數組參與指針運算,會降級為指針int (*p1)[3] = &arr[0];for(int i = 0; i < row_len;i++){for(int j = 0; j < col_len; j++){printf("%-6d", p1[i][j]);printf("%-6d", (*(p1+i))[j]);printf("%-6d", *(p1[i]+j));//列偏移printf("%-6d", *(*(p1+i)+j));}}printf("\n");
}int main()
{return 0;
}
數組指針和指針數組
數組指針
指針和數組中符號優先級
() > [] > *
通過指針引用二維數組
int arr[][] = {{2000},{},{}};
表示形式 | 含義 | 地址/值 |
---|---|---|
arr | 二維數組名,指向一維數組的arr[0],0行首地址 | 2000 |
arr[0],*****(arr + 0),*arr | 0行0列元素地址,數組降級指針 | 2000 |
arr + 1,&arr[1] | 1行首地址 | 2008 |
arr[1],*(arr + 1) | 1行0列元素a[1] [0]的地址 | 2008 |
arr[1]+2,*(arr + 1)+2,&arr[1] [2] | 1行2列元素a[1] [2]的地址 | 2012 |
* (a[1]+2), * (* (arr+1)+2),arr[1] [2] | 1行2列元素a[1] [2]的值 | 元素值為13 |
注意:二維數組中,數組整體的地址值 == 數組中0行元素的地址值 == 數組中0行0列元素的地址值
案例1
-
用指向元素的指針變量輸出二維數組元素的值
#include <stdio.h>int mian() {//定義一個二維數組int arr[3][4] = {10,20,30,40,100,200,300,400,1000,2000,3000,4000};//定義一個指針變量,用來指向數組中的元素int *p = arr[0];//獲取元素個數 行容量 * 列容量int len = (sizeof(arr) /sizeof(arr[0])) * (sizeof(arr[0]) / sizeof(arr[0][0]));//使用單層for循環遍歷二維數組,列偏移for(; p < arr[0] + len; p++){//每四個一行 if((p - arr[0]) % 4 == 0 && p != arr[0])printf("\n"); printf("%-6d", *p); }printf("\n");return 0; }
案例2
-
數組指針輸出二維數組任意行任意列的元素的值
指針數組
-
定義:指針數組是一個數組,數組中每一個元素都是一個指針。
-
特點:
- 先有指針,后有數組
- 指針數組的本質是一個數組,只是數組中的每一個元素是指針
-
語法:
數據類型 *數組名[容量];
案例
#include <stdio.h>int main()
{//定義三個變量int a = 10, b = 20, c = 30;//定義指針數組:先有指針,后有數組、int *arr[3] = {&a, &b, &c};//獲取大小int len = sizeof(arr) / sizeof(arr[0]);//遍歷數組for(int i = 0; i < len; i++){printf("%-3d", *arr[i]); }printf("\n");return 0;
}
- 建議:我們一般使用指針數組處理字符串,后續專門講解
數組指針與指針數組的區別
對比項 | 指針數組 | 數組指針 |
---|---|---|
定義 | 數組元素均為指針的數組 | 指向一個完整數組的指針 |
存儲內容 | 存儲多個指針,每個元素指向不同的內存地址 | 存儲單個指針,指向一個完整的數組(首地址) |
內存分配 | 每個指針元素獨立分配內存,可能分散 | 指向的數組內存連續的,指針本身存儲數組首地址 |
語法實例 | int *arr[5] 元素為5個int *指針 | int (*arr) [5] 指向5個int的數組的指針 |
訪問方式 | 通過下標訪問指針元素,再解引用 *arr[i] | 先解引用指針得到數組,再訪問元素 (*arr) [i] |
使用場景 | 管理多個獨立指針(如字符串數組、動態結構體數組) | 操作多維數組(如傳遞二維數組的行指針) |
內存布局 | [ptr1] --> 數據1 [ptr2] --> 數據2 … | ptr --> [數據1] [數據2]… |
示例代碼 | int a = 1,b = 2;int *arr[] = {&a,&b}; | int arr[2] [3] = {1,2,3,4,5,6};int (*ptr)[3] = arr; |