💖 技术宅,拯救世界!
🎁 对读者的话:相信奇迹的人本身和奇迹一样伟大
生命中最快乐的事情是拼搏,而非成功,生命中最痛苦的是懒散,而非失败。大家好,这里是ecember。今天我们来是深入的探讨一下指针中指针数组与数组指针的概念及其应用(以下结果均在VS2022中编译)。
🌹感谢大家的点赞 和关注 🌹,如果有需要可以看我主页专栏哟💖 |
⚡1. 字符指针
我们知道在指针的类型中有一种叫字符指针即 char*
int main()
{
char ch = '0';
char* pc = &ch;
*pc = 'a';
printf("%c\n", ch);
return 0;
}
存放字符的地址我们就得用字符指针。
笔试题1
int main()
{
const char* p1 = "abcdef";//常量字符串_与const无关
const char* p2 = "abcdef";//不会开辟另外的空间
char arr1[] = "abcdef";
char arr2[] = "abcdef";//数组开辟的空间是两块空间
if (p1 == p2)
{
printf("p1 == p2\n");
}
else
{
printf("p1 != p2\n");
}
if (arr1 == arr2)
{
printf("arr1 == arr2\n");
}
else
{
printf("arr1 != arr2\n");
}
return 0;
}
上述代码输出什么?这里我们必须清楚当我们用指针存放字符串时,实际上是存放的字符串首字符的地址,这里p1, p2指向同一个字符串,故存放的内容相同。而我们指定不同的数组时,即使内容相同,在内存中开辟的地址是不同的。
⚡2. 指针数组
顾名思义,指针数组是一个数组,存放指针的数组。
int main()
{
//整形数组
//int arr[10];//存放整型
字符数组
//char arr2[5];//存放字符
//int* arr[10];//存放整型指针的数组
//char* ch[5];//存放字符指针的数组
int a = 10;
int b = 20;
int c = 30;
/*int* p1 = &a;
int* p2 = &b;
int* p3 = &c;*/
int* arr[3] = { &a,&b,&c };
int i = 0;
for (i = 0; i < 3; i++)
{
printf("%d ", *arr[i]);//对数组内容解引用即得数据
}
return 0;
}
应用
int main()
{
int arr1[5] = { 1,2,3,4,5 };
int arr2[5] = { 2,3,4,5,6 };
int arr3[5] = { 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;
}
这里的parr数组即为指针数组,存放的是上述三个数组首元素的地址,parr[ i ]就相当于每个数组的数组名,即代表每一行首元素地址,可以通过加 j 来实现访问数组的每个元素。
⚡3. 数组指针
数组指针是指针?还是数组?答案是:指针。
我们已经熟悉:
整形指针: int * pint; 能够指向整形数据的指针。浮点型指针: float * pf; 能够指向浮点型数据的指针。那数组指针应该是:能够指向数组的指针。
那么指针数组的基本结构呢?
int *p1[10];
int (*p2)[10];
//p1, p2分别是什么?
解释:p2先和* 结合,说明p是一个指针变量,然后指着指向的是一个大小为10个整型的数组。所以p是一个指针,指向一个数组,叫数组指针。
这里要注意:[ ] 的优先级要高于* 号的,所以必须加上()来保证p先和*结合。
对于操作符的优先级,大家可以看看我这篇博客:操作符详解。
int main()
{
int arr[10] = { 0 };
int(*p)[10] = &arr;//数组指针
//p即为数组指针类型名——int(*)[10]加一表明跳过一个数组
return 0;
}
练习
int main()
{
char* arr[5] = { 0 };
char*(*p)[5] = &arr;
return 0;
}
其中p是什么?首先p先和 * 结合形成一个指针,然后我们看看后面又跟了一个 [ ]表明它指向一个5个元素数组,数组元素什么类型呢?——char * ,所以说p是一个指向数组元素为char*的数组的指针。
小科普
&arr VS arr
这俩到底有什么区别呢?
通常情况下,我们说的数组名都是数组首元素的地址
但是有两个例外:
1.sizeof(数组名),这里表示整个数组,sizeof计算的是整个数组的大小
2.&数组名,这里的表示的是取出整个数组的地址
数组指针的应用
void print2(int(*p)[5], int c, int r)
{
int i = 0;
for (i = 0; i < c; i++)
{
int j = 0;
for (j = 0; j < r; j++)
{
//p + i是指向第i行的
//*(p + i)相当于拿到了第i行,也相当于第i行的数组名
printf("%d ", *(*(p + i) + j));//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} };
//函数打印arr数组
print2(arr, 3, 5);//这里传过去的相当于就是第一行的行指针,也就是第一行的地址
return 0;
}
我们知道二位数组传参传过去的实际是第一行的地址,那么p + i 也就相当于拿到了第 i 行的地址,再解引用,就相当于拿到了数组名,即每行首元素的地址,再通过 +j 再解引用即访问到二维数组每一个元素。
⚡4. 结语
到这,我们的 《指针数组 VS 数组指针》 已经接近尾声了,后续我还会持续更新C语言相关内容,学习永无止境,就会永远只会留给有准备的人。希望我的博客对大家有所帮助,如果喜欢的可以 点赞+收藏哦,也随时欢迎大家在评论区及时指出我的错误。