目录
1.字符指针
在指针的类型当中,我们知道有一种字符指针:char*.
1.在日常中有两种使用方式
(1)将一个字符的地址储存
//最普通的指向一个字符
char p = 'w';
char* pa = &p;
在解引用中:只打印一个元素,即 w
(2)指向一个字符串,实际上也是指向第一个字符。将字符串首个字母H的地址放到p中,因为char类型解引用之后也只能存放一个字节的内容。
const char* pb = "Hello world!";
2.在解引用中:打印整个字符串。
//只打印首元素
printf("%c\n",*pb);
//打印字符串时,只需要给首元素地址就行。他会自动找到后面的字符,因为在内存中的存储是连续的
printf("%s\n",pb);
3.当字符指针指向一个常量字符串时,由于是常量字符串,具有不可更改性,所以不能再根据指针改变字符串内容,像这样
4。看这样一个例子:
像这样的字符串,在内存当中会单独开辟一块空间进行存储。
2.指针数组
(1).指针数组的理解
指针数组就是存放指针的数组。例如:
int* arr[10]; //整形指针的数组
char *arr[4]; //一级字符指针的数组
char **arr[5];//二级字符指针的数组
看这样一串代码:
int a = 10;
int b = 20;
int c = 30;
int d = 40;
int* arr1[4] = {&a,&b,&c,&d};
arr1 数组当中每一个元素都是int*类型,都是整形地址,分别指向一块内存空间,所以arr1就叫做一个指针数组。理解了指针数组的概念之后,那如何根据指针获取指针所指向的内容呢?
(2)指针数组的内容获取
还是上面的例子,如何将arr1数组中,abc的值打印出来呢?由数组的下标分别获取元素指针 ,再解引用,从而获取指针指向的内容。
例2:
int main()
{
int arr1[] = {1,2,3,4};
int arr2[] = {2,3,4,5};
int arr3[] = { 3,4,5,6 };
int arr4[] = { 5,6,7,8 };
int* parr[] = {arr1,arr2,arr3,arr4};//parr是一个整形指针数组,每一个元素作为各自的数组名分别指向一个一维数组
//如何将这些数字分别打印?
for (int i = 0; i < 4; i++)//声明一个变量用来记录parr数组的下标,找到每个数组的起始地址
{
for (int j = 0; j < 4; j++)//声明一个变量用来记录parr数组每一个元素指向的数组的下标
{
printf("%d ",(parr[i])[j]);//只需要给首元素地址就能打印整个数组
//parr[i]==*(parr+i)
}
printf("\n");
}
return 0;
}
在例2中,引发一个思考:数组名是各自首元素的地址都是int*,作为元素放到parr这一个指针数组当中, 那么parr可以认为是一个二级指针。也就是说这个例子 指针数组的数组名是由二级指针存放的。
int** p = parr;
3.数组指针
1.数组指针的理解和声明
数组指针,是指向一个数组的指针,他是指针。我们已经知道
整形指针: int * pint; 能够指向整形数据的指针。
浮点型指针: float * pf; 能够 指向浮点型数据的指针。
int main()
{
int arr[10] = {0};
//数组名是数组首元素的地址(除了放到sizeof(),或者&arr)
int* p = arr;//整形的地址放到整形指针当中
//parr的类型:int (* )[];
int (*parr) [10]=&arr;//取出数组的地址,应该放到数组指针当中
return 0;
}
parr就是一个数组指针。
老例子,注意区别
3.我们再举一个对比性的例子帮助理解
4.那数组指针是怎么使用的呢?
看下面的一串代码(相关辅助理解再代码的注释中):
void print1(int arr,int sz)//用数组接收
{
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ",arr[i]);
}
}
void print2(int *arr,int sz)//用指针接收首元素地址
{
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", *(arr+i));
}
}
void print3(int (*p)[10],int sz)//传整个数组的地址,用数组指针接收
{
int i = 0;
for (i = 0; i < 10; i++)
{
//三种写法
printf("%d ",(*p)[i]);//对p解引用找到这个数组,然后找元素。相当于parr指向数组的数组名
//p[i]==*(p+i)
printf("%d ",p[0][i]);//把数组指针p指向的整个数组当做一个二维数组的第一行,索引是0.然后取每一个元素
printf("%d ",*(*(p+0)+i));
}
}
int main()
{
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
int sz = sizeof(arr) / sizeof(arr[0]);
print1(arr,sz);
print2(arr,sz);
print3(&arr,sz);
return 0;
}
调用三个print函数,分别是三种不同的做法。其中第三种就用到了数组指针。
而我们最常用的就是用数组指针来获得二维数组,看下面的例子:
#include <stdio.h>
void print1(int(*p)[3], int r, int c)//用一个指向一维数组的数组指针接收,这个数组有3个元素(二维数组的三列)
{
int i = 0;
for (i = 0; i < r; i++)
{
int j = 0;
for (j = 0; j < c; j++)
{
printf("%d ",p[i][j]);
//printf("%d ",*(p+i)[j]);
}
printf("\n");
}
}
int main()
{
int arr[3][3] = {1,2,3,4,5,6,7,8,9};
print1(arr,3,3);//二维数组,数组名表示首元素,这个首元素可以理解为二维数组的第一行,把第一行的地址(一个数组地址)传过去
return 0;
}
理解了这个例子之后,让我们再来分析一下这几个代码是什么意思:
int arr[5];
int *parr1[10];
int (*parr2)[10];
int (*parr3[10])[5];
解析如图:
这就是集中常见指针的理解和应用。如有问题欢迎指正,让我们一起加油吧!