指针进阶·字符指针(一)

目录

引子

​指针数组

​使用场景

         ​数组指针

        概念

        例子 

​关于数组名的解析 

​正题

        特色用法

        模拟二维数组 

​        练习 

结束语:


引子

我们可以用指针的方式,通过地址的形式来改变所指的值。

#include<stdio.h>
int main() {

	char c = 'a';
	char* pc = &c;

	printf("%c\n", *pc);

	*pc = 'A';
	printf("%c\n",*pc);


	return 0;
}

字符串的形式

#include<stdio.h>

int main() {
	
	const char* p = "abcdef";  //把字符串首字母a的地址,赋值给了p
                               //这里用了 const 来表示,所指字符串不可以修改
	printf("%s\n",p);        

	return 0;
}

​

指针数组

当我们要把相同类型的数据放在一起时,我们通常会创立一个数组

int arr[10];   //整型数组        int  int  int  int  int  int……

char ch[20];  //字符数组        char  char  char  char  char……

int *arr2[10];  //存放整型指针的数组  int*  int*  int*  int*  int*……

char*ch2[20];  //存放字符指针的数组  char*  char*  char*  char*  char*……

使用场景

//运用指针数组,模拟二维数组
#include<stdio.h>
int main()
{
	int arr1[] = { 1,2,3,4,5 };
	int arr2[] = { 2,3,4,5,6 };
	int arr3[] = { 3,4,5,6,7 };

	int* parr[3] = { arr1,arr2,arr3 };

	int i = 0;
	for ( i = 0; i < 3; i++)
	{
		int j = 0;
		for ( j = 0; j < 5; j++)
		{
			printf("%d ",*(parr[i]+j));
			//printf("%d ",parr[i][j]);        //也可以直接运用二维数组的打印方式
		}
		printf("\n");
	}

	return 0;
}

数组指针

概念

就像下面的情况

数组指针   --     指针        --        指向数组的指针        //就像下面的两个例子

整型指针        --        指向整型的指针

字符指针        --        指向字符的指针

例子 

int *p1[10];          //这里 p1 [10] 先结合,表明它是一个数组有10个元素,所以p1是数组名

                           //剩下的 int * 就是它的类型了,所以p1指针数组

int (*p2)[10];       //这里p2*号先结合,说明p2指针

                          //之后再和 [10] 结合,表示p2指向的是一个数组,有10个元素在与int结合

                         //表明它指向整型数组

          //即p2是数组指针,p2可以指向一个数组,该数组有10个元素,每个元素是int类型

那么如何使用呢?

关于数组名的解析 

为了更好的理解我们先来回顾一下数组名

​//再次讨论数组名
#include<stdio.h>
int main() {

	int arr[10] = { 0 };
	printf("%p\n",arr);			//通过这三行代码我们可以确定
	printf("%p\n",&arr[0]);		//数组名通常都是首元素的地址
	printf("%p\n", &arr);		//这里数组的地址也是首元素的地址哦
								
	int sz = sizeof(arr);		//在这里的话就情况不一样了
	printf("%d\n",sz);			//在这里我们发现这里不是表示地址的大小
								//而是整个数组的大小
	return 0;

}

​

结果如下 

 

第二种情况 

#include<stdio.h>

int main() {
                                   //我们让数组+1,这样就可以看出差别了
	int arr[10] = { 0 };

	printf("%p\n", arr);		  //这里是指向数组中下一个元素
	printf("%p\n\n", arr+1);		

	printf("%p\n", &arr[0]);	
	printf("%p\n\n", &arr[0]+1);    //这里也是指向数组中下一个元素

	printf("%p\n", &arr);		
	printf("%p\n\n", &arr+1);	//这里数组的地址也是首元素的地址
								//所以就会直接跳过数组指向下一块区域

                        
	return 0;

}

总结如下 

//在数组中数组名通常都是首元素的地址

//但是我们需要明白这个 “通常” 是有两个例外的
//1.sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小
//2.&数组名,这里的数组名表示的依然是整个数组,所以&数组名取出的是整个数组的地址

正题

#include<stdio.h>

int main() {
    int arr[10] = { 0 };
    int* p = arr;                                //指向了数组中的元素
    printf("%d",*(p+1));

    int (*p2)[10] = &arr;                    //和其他类型的指针有相似之处
    //“int” arr的类型  ,(*p)表示它是一个指针,[10]表示arr有十个元素
    //int (*)[10]  把名字去掉就是它的类型了

   //即  p2的类型是 int (*)[10]
}

//同理

char *arr[5] = {0};

//用指针的形式指出来

结果:

#include<stdio.h>

int main() {
    char* arr[5] = { 0 };
    char* (*pc)[5] = &arr;                //这样才是正确的形式        

                                                    //这里 arr 的类型是 char*

    return 0;
}

需要注意的是

#include<stdio.h>
int main() {
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };        //这种写法是不对的
	int(*p)[] = &arr;

	return 0;
}

会警告    C4048    “int (*)[0]”和“int (*)[10]”数组的下标不同 

正确的写法应该是 

#include<stdio.h>
int main() {
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int(*p)[10] = &arr;

	return 0;
}

特色用法

非常规的用法(不推荐使用)

#include<stdio.h>
int main() {
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int(*p)[10] = &arr;

	int i = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);
	for ( i = 0; i < sz; i++)
	{
		printf("%d ",*(*p+i));//p是指向数组的,*p其实就相当于数组名,数组名又是数组首元素的地址
							  //所以*p本质上是数组首元素的地址
	}

	return 0;
}

 一般我们用指针的时候是这样用的

#include<stdio.h>
int main() {
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int* p = arr;

	int i = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);

	for ( i = 0; i < sz; i++)
	{
		printf("%d ",*(p+i));
	}

	return 0;
}

 这样就好多了,舒服

模拟二维数组 

 模拟二维数组,利用数组指针可以模拟出二维数组的基本实现

#include<stdio.h>
print1(int arr[3][5], int r, int c)
{
	int i = 0;
	for ( i = 0; i < r; i++)
	{
		int j = 0;
		for ( j = 0; j < c; j++)
		{
			printf("%d ",arr[i][j]);
		}
		printf("\n");
	}
	
}

int main() {

	int arr[3][5] = { 1,2,3,4,5,2,3,4,5,6,3,4,5,6,7 }; 
	print1(arr, 3, 5);

	return 0;
}

模拟后

#include<stdio.h>
print2(int (*p)[5], int r, int c)    //这里使用数组指针的方式接收数组地址                                            
{                                    //指向一维数组的指针
	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][5] = { 1,2,3,4,5,2,3,4,5,6,3,4,5,6,7 }; 
	print2(arr, 3, 5);        //这里 arr 传过去的是数组的首地址,即首个一维数组
                             //arr表示第一行的地址
						    //第一行的地址,是一个一维数组的地址
	return 0;
}

​

​

​

int (*p)[5];

p 的类型是:int(*)[5]

p 是指向一个整型数组的,数组5个元素 int [5]

p+1  ---  跳过一个5个int元素的数组 

练习 

学了指针数组和数组指针我们来一起回顾并看看下面代码的意思:

int arr[5];                                                                                                            //整型数组
int* parr1[10];                                                                                                //整型指针数组
int(*parr2)[10];                                                                                                    //数组指针
int(*parr3[10])[5];                                                                                 //存放数组指针的数组

结束语:

         人似云

云随风而来,需尽兴而去。

了却身边事,沉下心里闲。

晚看云霞景,心向天边云。

未完持续更新中……

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

清风玉骨

爱了!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值