前言
我们前面对指针有了初步的学习,本篇文章我们来对指针进行较为深入的学习。
一、字符指针
在指针的类型中有一种指针类型为字符指针 char* ;
一般情况下我们就是把一个字符的地址放入字符指针中,但我们这里介绍一下另一种用法:
int main() { const char* p = "hello world";//这里是把一个字符串放到指针变量里了吗? printf("%c\n", *p); return 0; }
显然是不可能把一个字符串放到指针变量里的,指针变量这里只有四个字节,根本放不下,我们来打印一下看一看到底放的是啥。
我们这里其实是把字符串首字符的地址给了p,并没有把整个字符串给p,但是如果想打印整个字符串该怎么打印呢?只需要把%c换成%s,*p换成p就可以了,我只需要知道你的起始地址,就能打印出你全部的内容。
二、数组指针
数组指针是指针?还是数组?
答案是:指针。
我们前面一起学习过:
整形指针: int * p; 能够指向整形数据的指针。
浮点型指针: float * p; 能够指向浮点型数据的指针。
那数组指针应该是:能够指向数组的指针。
那么数组指针如何定义呢?
解释:
int (*p)[10] //解释:p先和*结合,说明p是一个指针变量,然后指向的是一个大小为10个整型的数组。所以p是一个指针,指向一个数组,叫数组指针。
那么数组指针应该怎么用呢?这里我们先知道一个概念:数组的地址
我们&arr取出的是数组的地址,注意:数组的地址 和 数组首元素的地址意义是不一样的,但他们在数值上是一样的。我们来看一段代码。
我们可以看出,两个地址数值上是相等的,但是我们分别给这两个地址+1,结果却不一样。&arr+1是向后跳过一个数组,这个数组10个元素,就是向后跳过40个字节。&arr[0]+1是向后跳过一个元素,就是向后跳过四个字节。讲到这里我们就理解了数组的地址的意思了。数组指针存放的是数组的地址,即&arr。
我们再来看一下数组指针怎么用。我们举个例子用数组指针来打印数组中的元素。请看下面代码:
#define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> void printf1(int (*p)[5]) { 2.实参传过来整个数组的地址,形参用数组指针来接收。 for (int i = 0; i <= 4; i++) { printf("%d ", *(*p + i)); 3.*p拿到整个数组,即数组名,即数组首元素地址,(*p+i)拿到数组每个元素的地址,再*(*p + i)拿到数组的每个元素。 } } int main() { int arr[5] = { 0,1,2,3,4,}; printf1(&arr); 1.我们把整个数组的元素传进去 return 0; }
我们可以发现,这样做虽然用到了数组指针,但这个算法很麻烦。我们完全没有必要用这种方式来打印数组中的元素,所以数组指针很少用在一维数组中,这里只是通过这个例子来学习理解
数组指针的用法。
我们再来用二维数组举例来学习一下数组指针的用法。还是用打印数组的元素来举例
(注意:二维数组的数组名表示首元素地址时表示的是第一行的地址。)
#include <stdio.h> void printf1(int (*p)[2]) { //2.用数组指针来接受 for (int i = 0; i <= 1; i++) { for(int j=0;j<=1;j++) { printf("%d ", *(*(p+i)+j)); //3.p+i相当于指向第i行,*(p+i)相当于拿到了第i行的数组名,*(p+i)+j相当于指向第i行第j列的某个元素,也就是找到了它的地址。 *(*(p+i)+j)相当于通过它的地址找到了第i行第j列的某个元素 } } } int main() { int arr[2][2] = { 0,1,2,3,}; printf1(&arr); //1.传过去整个数组的地址 return 0; }
这里重点理解学习一下数组指针是如何使用的。这里只是通过这个例子来学习理解数组指针的用法。
三、指针数组
先看一下下面这三个
int arr[10]={0}; //存放整形数据的数组 char arr[10]={0}; //存放字符数据的数组 float arr[10]={0}; //存放浮点型数据的数组
那么指针数组就是一个存放指针的数组。(指针存放的是地址,而指针本身也要存放起来。)
int* arr1[10]; //整形指针的数组 char *arr2[4]; //字符指针的数组 char **arr3[5];//二级字符指针的数组
这个具体怎么用呢?请看下面代码:
int main() { int a = 2; int b = 3; int* p1 = &a; int* p2 = &b; int* arr[2] = { p1,p2, }; for (int i = 0; i <= 1; i++) { printf("%d ", * (arr[i]); //arr[i]拿到地址,再解引用拿到元素 } return 0; }
模拟二维数组
我们还可以用这个来模拟一个二维数组,请看代码:
#include <stdio.h> int main() { int arr1[3] = { 0,1,2 }; int arr2[3] = { 3,4,5 }; int arr3[3] = { 6,7,8 }; int* arr[3] = { arr1,arr2,arr3}; //数组名表示首元素地址,所以可以放进指针数组 for (int i = 0; i <= 2; i++) { for (int j = 0; j <= 2; j++) { printf("%d", *(arr[i] + j)); //arr[i]拿到第i个数组的首元素地址,+j指向第i个数组中的第j个元素,再解引用表示通过地址找到了这个元素。 } printf("\n"); } return 0; }
运行结果为:
这样我们就模拟出了一个3行3列的二维数组。
总结
本篇文章学习了指针的一些较为深的一些知识,希望大家多去理解和学习。由于指针的内容较多,下篇文章继续来学习指针的进阶,本篇文章就先学习到这里。
本篇文章内容结束,感谢大家观看。如果意见或建议,可以在评论区留言,您的点赞是我更新的动力。我们下篇文章再见。