目录
字符指针
#include<stdio.h>
int main()
{
char arr[] = "abc";
char* p1 = arr;
*p1 = 'r';
printf("%s", arr);
return 0;
}
#include<stdio.h>
int main()
{
char* p2 = "abc";//p2指向的是a的地址
*p2 = 'r';
printf("%s", p2);
return 0;
}
两代码执行结果如何呢?
:第一个代码正常执行,第二个会报错。尽管 代码二的p2 存的也是首字符的地址,但是这种写法使“abc”成为常量字符串,所以不能进行修改。所以就出现了这种更为安全的写法:const char* p="abc"; (常量指针)
习题检验(源于剑指offer)
#include <stdio.h>
int main()
{
char str1[] = "hello bit.";
char str2[] = "hello bit.";
const char* str3 = "hello bit.";
const char* str4 = "hello bit.";
if (str1 == str2) //数组名(首元素地址)
printf("str1 and str2 are same\n");
else
printf("str1 and str2 are not same\n");
if (str3 == str4)
printf("str3 and str4 are same\n");
else
printf("str3 and str4 are not same\n");
return 0;
}
所以说:str3 与 str4 存的地址一模一样。
而 &str3 与 &str4 是不相等的,因为它们是两个不同的字符指针变量,不在同一个空间,当然不同,千万别把它们看成数组名了。
指针数组
问:指针数组是指针还是数组呢?
:是数组,指针只是这个数组存放数据的类型而已,存放的是指针,即指向指针的数组。
#include<stdio.h>
int main()
{
int a = 1;
int b = 2;
int* arr[] = { &a,&b };//指针数组存放指针(地址)
return 0;
}
这就是指针数组的创建。那么该说说使用了:(模拟二维数组)
但是这三个 arr 数组并不是连续存放在内存中的,ptr指针数组存的内容是连续存放的。
数组指针
提到了指针数组,那么就必须谈谈它的好兄弟了——数组指针。
数组指针是一个指向数组的指针(存放数组的地址),类型取决于数组的类型。
int arr[5];
//arr是整型数组,该如何存放。
//数组指针
int(*p)[5]=&arr;//p表示是一个指针,所以要先括起来,int[5]是arr的类型
//对于一个变量来说,去掉变量名就是变量类型
//所以上面的数组指针的类型:int(*)[5]
那么int* arr[5] 这个(指针)数组又该如何存放呢?
同理:int*(*p)[5]=&arr;
使用数组指针打印数组元素
我们知道用指针打印数组各个元素时,通过指针加1解引用就可以。
因为在之间写的博客也提到过整型数组的指针加减1就是跳过一个一个整形的字节空间,解引用就相当于访问当前空间的数据。
那考虑考虑用数组指针来打印数组的各个元素,还可以直接加1嘛
#include<stdio.h>
int main()
{
int arr[10] = { 0,1,2,3,4,5,6,7,8,9 };
int(*p)[10] = &arr;//创建一个数组指针p存放&arr,p的类型就是 int(*)[10]
for (int i = 0; i < 10; i++)
{
printf("%d ", *((*p) + i));//
}
return 0;
}
那么该怎么理解 *((*p) + i) 呢?
数组指针p就相当于&arr,我们知道&arr取出的是整个数组的地址,加一就跳过一个数组类型的地址,在这里就是4*10个字节的空间。
*p就相当于 * &arr,那么*p 不就等价于arr(数组名,首元素地址嘛)那么((*p)+i)不就是(arr+i)嘛。
再次解引用不就得到各个元素嘛
而*((*p)+i)也可以写成(*p)[i]
这里只是介绍一下用数组指针打印数组各元素的方法,但是并不提倡哈。
二维数组传参(用数组指针接收)
在之前的三子棋和扫雷中我们见到了二维数组传参,形参也是一个二维数组的形式。
我们知道一维数组的数组名就是首元素的地址,那么二维数组的数组名呢——同样是首元素的地址。但对于二维数组来说首元素地址是第一行的元素地址。
int arr[2][3]={1,2,3,4,5,6};
//1 2 3
//4 5 6
//而arr[0]与arr[1]就相当于两个一维数组的数组名,
//此时就可以把该二维数组看成一个一维数组。存的是arr[0]与arr[1]
//所以二维数组的数组名也就是arr[0]的地址,也就是第一行元素的地址。
有了这些了解,那么二维数组传参,传的是首行元素的地址,那么不就得用数组指针来接收嘛。
实践
#include<stdio.h>
void Print(int(*p)[3], int l, int r)//用数组指针接收,每行三个元素
{
for (int i = 0; i < l; i++)
{
for (int j = 0; j < r; j++)
{
printf("%d ", (*(p + i))[j]);// *(p+i)表示的是第i行数组名(首元素地址)
}
printf("\n");
}
}
int main()
{
int arr[2][3] = { 1,2,3,4,5,6 };
Print(arr, 2, 3);//二维数组名
return 0;
}
//这里也仅仅是了解一下这种写法,但是这种代码可读性差,不建议写,还是二维数组接收更佳。