指针的理解与应用(上)——几种常见指针

目录

1.字符指针

2.指针数组

3.数组指针


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。看这样一个例子:

像这样的字符串,在内存当中会单独开辟一块空间进行存储。

当几个指针。指向同一个字符串的时候,他们实际会指向同一块内存。但是用相同的常量字符串去初始
化不同的数组的时候就会开辟出不同的内存块。所以 str1 str2 不同, str3 str4 不同。

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就是一个数组指针。

p先和*结合,说明p是一个指针变量,然后指着指向的是一个大小为10个整型的数组。所以p是一个 指针,指向一个数组,叫数组指针.
         2. 我们知道 arr 是数组名,数组名表示数组首元素的地址。
&arr取出的是整个数组的地址放到数组指针当中,而 不同指针类型加一,跳过的字节数目是不一样的。
    老例子,注意区别

         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];

 解析如图:

 这就是集中常见指针的理解和应用。如有问题欢迎指正,让我们一起加油吧!

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值