【参考课程:B站 BV1Vm4y1r7jY】
//指针是用于存放地址的变量,地址唯一标识一块内存空间。
//指针的大小是固定的4/8个字节(32/64位平台)
//指针的类型 决定了指针的+-整数的步长,以及指针解引用操作的权限
//指针的运算
1.字符指针 char*
#include<stdio.h>
int main()
{
//字符指针可以存放一个字符变量的地址
char ch = 'c';
char* pch = &ch;
//字符指针可以存放字符串首字符的地址//本质还是存放字符的地址
char* p = "abcdef";
char chr[] = "abcdef";
//将字符串[a][b][c][d][e][f][\0]的首字符[a]的【地址】存放在p中
printf("%c\n", *p);//a//解引用地址p,%c:输出其中存放的字符
printf("%c\n", p);//?//把地址p:0x00007ff6e3369ca4,%c:以字符形式输出
printf("%s\n", p);//abcdef//从起始地址(p存放的'a'的地址)开始打印字符串
//%s:需要给定一个地址,%s从这个地址开始依次输出字符,直到遇到字符[\0]停止
//与数组名类似:
printf("%s\n", chr);//abcdef
return 0;
}
注意:
char* p = "abcdef";
是将常量字符串"abcdef"的首字符地址赋给 p
常量字符串的内容不能被更改,所以此处严谨书写代码应为: //const修饰指针变量
const char* p = "abcdef";
【例题】
#include<stdio.h> int main() { const char* p1 = "abcdef"; const char* p2 = "abcdef"; //"abcdef"为常量字符串,在内存中储存在【只读数据区】 //【只读数据区】内储存的数据只可读取使用,不可做更改--相同的数据在【只读数据区】内只储存1份 //p1 p2都存放的是储存在【只读数据区】的常量字符串"abcdef"的首字符地址→∴p1 == p2 if (p1 == p2) printf("p1==p2\n"); else printf("p1!=p2\n"); char arr1[] = "abcdef"; char arr2[] = "abcdef"; //此处arr1 arr2创建了2个独立数组,这两个数组内容可变,只是数组的初始化恰巧相同 //数组名是数组首元素地址→arr1 arr2指向两个不同数组的首元素地址→∴arr1 != arr2 if (arr1 == arr2) printf("arr1==arr2"); else printf("arr1!=arr2"); return 0; }
结果输出:
2.指针数组
//指针数组--是数组,是用于存放指针的数组
int* arr1[3]; //存放整型指针的数组
char* arr2[7]; //存放字符指针的数组
char** arr3[21]; //存放二级字符指针的数组
【例】用指针数组将一维数组模拟组合成二维数组
#include<stdio.h> int main() { int arr1[4] = { 1,2,3,4 }; int arr2[4] = { 2,3,4,5 }; int arr3[4] = { 3,4,5,6 }; int arr4[4] = { 4,5,6,7 }; int arr5[4] = { 5,6,7,8 }; int* parr[5] = { arr1,arr2,arr3,arr4,arr5 }; for (int i = 0; i < 5; i++) { for (int j = 0; j < 4; j++) { printf("%d ", *(parr[i] + j)); //p[i] <==> *(p+i) //∴此处还可写为: //printf("%d ", *(parr[i][j]); } printf("\n"); } return 0; }
⭐不同:
二维数组在内存中连续存放
而用指针数组将一维数组模拟组合成二维数组,其中的一维数组与一维数组之间内存不一定连续
※指针数组可用于存储字符串
3.数组指针 int(*)[n]
//类型:int(*)[n] //int表示数组元素类型;n为数组元素个数,不可省略
//数组指针--是指针,是指向数组的指针,用于存放数组的地址
int* p1[10]; //p1是指针数组,数组元素类型是int*--整型指针
int(*p2)[10]; //p2是【数组指针】指向有10个元素的int类型数组
int arr[10] = { 0 };
int* p1 = arr; //p1存放【数组首元素】地址
int(*p2)[10] = &arr; //p2存放【整个数组】arr的地址
char* arr[5] = { 0 }; //arr[5]是指针数组
char* (*pc)[5] = &arr; //pc存放arr[5]数组的地址,pc是数组指针--类型:char*(*)[5]
⭐再次讨论数组名
- 数组名通常表示的都是数组首元素地址
#include<stdio.h> int main() { int arr[10] = { 0 }; printf("%p\n", arr); //0000003B4A0FFB48 printf("%p\n", &arr[0]); //0000003B4A0FFB48 return 0; }
- 但有2个例外:
- sizeof(数组名) -这里的数组名表示整个数组,计算的是整个数组的大小
//注意括号里只单独放数组名#include<stdio.h> int main() { int arr[10] = { 0 }; printf("%d\n", sizeof(arr)); //40 //整个数组的字节大小 printf("%d\n", sizeof(arr+0)); //8 //此处打印的是类型为 int* 的变量的字节大小 //sizeof(arr+i)打印的是指向数组元素arr[i]的指针的大小 //arr+0表示数组arr的首地址加上偏移量0,实际上就是指向数组第一个元素的指针。 printf("%d\n", sizeof(arr[0])); //4 //单个元素的字节大小 return 0; }
- &数组名 -取出的是整个数组的地址
#include<stdio.h> int main() { int arr[10] = { 0 }; printf("%p\n", arr); //0000007307EFF548 printf("%p\n", arr+1); //0000007307EFF54C==0000007307EFF548 + 4 printf("%p\n", &arr); //0000007307EFF548 printf("%p\n", &arr+1); //0000007307EFF570==0000007307EFF548 + 40 return 0; }
数组指针的运用:
- *(数组指针) --本质是数组名--数组首元素地址
⭐<使用数组指针打印数组>可行,但非常不建议使用这种操作#include<stdio.h> int main() { int arr[] = { 0,1,2,3,4,5,6,7,8,9 }; int(*parr)[10] = &arr; //parr指向数组→*parr找到数组整体,相当于数组名→数组名是首元素地址 //∴ *parr 本质上是数组首元素地址 /*使用数组指针parr打印整个数组*/ int i = 0; int sz = sizeof(arr) / sizeof(arr[0]); for (i = 0; i < sz; i++) { printf("%d ", (*parr)[i]); //printf("%d ", *(*parr + i)); 效果相同 } return 0; }
- 数组指针的常见使用方法:
⭐二维数组数组名 == 二维数组首元素地址 == 二维数组的第一行数组的数组地址
*(二维数组名) == (二维数组第一行)一维数组的数组名
*(二维数组名+n) == (二维数组)n行一维数组的数组名#include<stdio.h> int main() { int a[3][5] = { 1,2,3,4,5,2,3,4,5,6,3,4,5,6,7 }; /*数组名--表示数组首元素地址 二维数组首元素为第一行数组 ∴二维数组数组名==第一行数组的数组地址*/ //自定义函数printarr打印二维数组 void printarr(int(*arr)[5], int row, int col);//形参名分别为 arr, row, col //由于这里二维数组的第一行数组有5个元素, //∴要把二维数组的数组名 传参的参数类型写为:int(* )[5] printarr(a, 3, 5);//传参调用函数 return 0; } void printarr(int(*arr)[5],int row, int col) { for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) {// *(二维数组名+n) == (二维数组)n行一维数组的数组名 printf("%d ", *(*(arr+i)+j)); //printf("%d ", (*(arr+i))[j]); 效果相同 //[]优先级大于*的优先级,所以要把*(arr+i)括起来 } printf("\n"); } }