指针进阶很难理解?小春宝带你慢慢理解指针进阶内容

目录

指针进阶

字符指针

指针数组和数组指针

指针数组

数组指针

指针数组和数组指针联系二维数组的使用


 

 

指针进阶

今天小春宝将给大家分享指针进阶内容的理解

字符指针

在指针类型中有一种非常常见且好用的指针类型,字符指针char*

今天给大家讲解一下这个字符指针的特殊用法

常见的char*用法
char c='a';
char*ptr_c=&c;
char str[]="buildxcb";
char*ptr_str=str;
新用法
char*string="buildxcb";

这里的用法并不是将“buildxcb”这个字符串的地址放在string中,而是将首字母‘b’的地址存放在string中,我们都知道指针并不能向内存申请一段空间,并且能够正常使用的指针(非野指针)必须指向内存中已经开辟的一段空间,并且以下的代码都是错误的

int* p = &1;
char* p_c = &'a';

那么字符指针的这个功能是怎么实现的,又有什么意义呢?

首先我们都只能操作系统中将内存进行了分区,从上往下是栈区,堆区,静态区,常量区,前三个区相信大家都比较熟悉,但是其实还有常量区这第四个区域,常量区储存的是常量和一些公共的代码,函数的代码就储存在这,同时常量字符串就存储在这里,所以这段特殊的代码正确的原因是在常量区开辟了一个空间用于存储常量字符串“buildxcb”,然后将b的地址存放在指针string中,这个时候就有一个问题了,大家都知道常量是不可以修改的,所以这句代码其实不够严谨,在cpp中这段代码可能会报错,所以我们正确的写法应该是

const char*string="buildxcb";

那么这段代码存在的意义又是什么呢?首先我们知道C语言中是没有字符串类型的,我们要表示字符串的时候需要借助字符数组,那么这种写法的存在就使得描述字符串增加了一种方式

指针数组和数组指针

指针数组

指针数组,中心词是数组,所以指针数组本质上是数组,当时数组中存放的是指针

int* arr_int[10]; //存放整形指针
char *arr_char[4];  //存放字符指针
char **arr_char_ptr[5]; //存放二级字符指针

数组指针

数组指针,中心词是指针,所以数组指针是一种指针,指针类型决定指针指向数据的类型,那么数组指针的意思便是一种指向数组的指针,接下来看一下指针数组

int(*arr)[10];//指针数组
int* arr[10];//数组指针

我们可以发现有没有括号标识符arr的意义就变了,那么为什么会出现这种情况呢?

基本数据类型声明     变量类型 标识符 数组类型变声

数组类型变量的声明    数组数据类型 数组名[]

指针类型变量的声明     指针数据类型  *标识符;

所以我们可以发现变量的声明是由两部分构成,标识符和变量类型,表达式1和表达式2的标识符都是arr,那么剩下的部分就是arr的类型,首先在变量声明时谁先和标识符接触代表标识符的类型是什么,在没有大括号的情况下[]的优先级高于*。

没有小括号时,[]先和arr接触,所以这个arr本质上是一个数组,剩余的都为数组的数据类型即int*,当有小括号的时候,arr先和*结合,所以arr是一个指针变量,剩余部分即为指针数据类型int [10],即长度为10的整形数组。

指针数组和数组指针联系二维数组的使用

下面这段用指针数组和数组指针遍历二维数组的代码

#include<stdio.h>
int main()
{
	int arr[5][5] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25 };
	int* parr[5] = {NULL};
	for (int i = 0; i < 5; i++)
	{
		parr[i] = arr[i];
	}
	for (int i = 0; i < 5; i++)
	{
		for (int j = 0; j < 5; j++)
		{
			printf("%2d ", parr[i][j]);
		}
		printf("n");
	}

	return 0;
}

首先我们使用指针数组进行遍历,我们二维数组可以看成是一维数组的数组,所以二维数组的每一个元素其实都是一个一维数组,都是int []或者int*类型,所以我们第一步需要将指针数组的每一个元素和二维数组的每一行对应,再进行遍历

#include<stdio.h>
int main()
{
	int arr[5][5] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25 };
	int(*parr)[5] = arr;
	for (int i = 0; i < 5; i++)
	{
		for (int j = 0; j < 5; j++)
		{
			printf("%2d ", parr[i][j]);
		}
		printf("n");
	}

	return 0;
}

二维数组arr的第一个元素是一个一维数组,之前也提到过,数组名就是常量指针,那么二维数组名arr指向的是一个一维数组,所以二维数组名就是一个数组指针,所以直接使用数组指针遍历即可

int arr[5];
int *parr1[10];
int (*parr2)[10];
int (*parr3[10])[5];

最后我们来分析一下

1.arr和[]结合,所以arr是一个数组,长度为5的数组,数组的元素类型为整形,所以arr是一个长度为5的整形数组

2.*比[]优先级高,parr1和[]结合,parr1是一个长度为10的数组,剩余的int*为parr1的元素类型int*,所以parr1是一个长度为10的,元素类型为int*的指针数组

3.parr2与*结合,所以parr2为指针,剩余的int [10]为parr2指向的元素的类型,即长度为10的整形数组,所以parr2是一个指向长度为10的整形数组的指针

4.首先分析*parr3[10],parr3是一个长度为10的数组,剩余的int (*)[5],所以parr3的每一个元素都是一个指向长度为5的整形数组的指针,总结parr3是一个长度为10,数组元素为指向长度为5的整形数组的指针,是数组指针数组。

今天的分享到此结束,希望看到这的小伙伴们,给个三连哦!