目录
前言
对于指针,我们已经有了初步认识(可以看我写的指针详解那一篇文章)。
简单总结一下基本概念:
1、指针就是一个变量,用来存放地址,地址唯一标识一块空间。
2、指针的大小是4/8个字节(32位平台为4字节,64位平台为8字节)
3、指针是有类型的,指针的类型决定了指针的+-的步长以及指针解引用操作时候计算机如何看待指针所指向的内容。
4、指针的运算(指针+-常数;指针-指针;指针与指针的比较)
对于基本概念了解后,现在我们进行指针进阶,对指针进行进一步的深入分析。
1、字符指针
举例两种用法:
第一种,指向字符变量,可以操作字符变量。
#include<stdio.h>
int main()
{
char ch = "w";
char* pc = &ch;
*pc = 'b';
printf("%c\n", ch);
return 0;
}
还有一种,指向字符串。
#include <stdio.h>
int main()
{
const char* p = "abcdef";
printf("%s\n", p);
return 0;
}
第二种用指针指向字符串,实际上是把字符串首元素的地址传给了指针变量。而对于常量符串来说,其内容不可被更改,因此用const'修饰*p表示*p的无法更改。
看一个例子:
原因:对于常量字符串,放在内存的只读数据区里面,这个空间只能读不能写,只能用不能改变其内容,对于同样的常量字符串,会放在同一个地址,因此p1和p2指向同一个地址,因此p1==p2。
但是对于arr1和arr2来说,它们是被创建的两个数组,自然会在内存中开辟不同的地址,“abcdef”只不过是对其的初始化而已。所以这两个数组的首元素地址是不同的。
2、指针数组
是数组,是用来存放指针的数组。
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;
int j = 0;
for (i = 0;i < 3;i++)
{
for (j = 0;j < 5;j++)
{
printf("%d ", *(parr[i] + j));
}
printf("\n");
}
return 0;
}
parr就是一个指针数组,它的内部存放了三个地址。
对每个地址进行访问,就能打印出所有元素的值。其实对于指针数组来讲,它其实是模拟了一个二维数组。访问时可以直接用parr[i][j];效果完全相同。
3、数组指针
是指针,是指向数组的指针。
3.1数组指针的定义
int* p1[10]; p1是指针数组
int (*p2)[10]; p2是数组指针
p2数组指针可以指向一个数组,该数组有10个元素,每个元素是int类型
要将明白数组指针,必须要先弄懂数组名的概念。
3.2 数组名VS&数组名
数组名通常表示的是首元素的地址,但是有两个例外:
1.sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小。
2.&数组名,这里的数组名表示的依然是整个数组,所以&数组名取出的是整个数组的地址
&数组名从值上来看,和数组名是一样的,都表示了数组首元素的地址,但是,他们的区别是什么?我们都加一看看。
、
我们发现,arr加1加了4,而&arr加1加了40。由此我们知道,&数组名之后,它会表示整个数组的地址,+1直接跳过整个数组。
那么想&arr这样的数据,如果我们想用变量去存放它,我们该用什么变量去存放它呢。答案就是数组指针。“数组指针就是指向数组的指针”,这样我们便理解了这句话。
int(*p2)[10] = &arr;
这样去定义就能存放&arr,不加括号p2会优先和[]结合成为数组,因此需要用括号将*和p2括起来,确保其是一个指针,后面[]中放的数是arr的元素个数。int指的是arr元素的类型。
3.3数组指针的运用
这是一个运用的例子,有几个要注意的点。1、在定义数组指针时,[]中必须指明数组的元素个数。2、在输出时,一定要将*p用()括起来,不然p会优先和[]结合,变成野指针。
但是我们一般不这么使用,因为用指针访问数组只需要用*p指向arr就好了。
数组指针不是应用在这种情况的,数组指针一般运用在二维及以上的数组处理。
这个例子告诉我们,当函数传参时二维数组时,形参可以用数组指针去接收。这样去使用数组指针是最舒适的。
到此,指针进阶(一)结束,后面还有两篇进行讲解,还包括的内容有函数传参如何用指针接收、函数指针、函数指针数组、指向函数指针数组的指针、回调函数。