今天我们主要聊一下指针和数组的亲密关系,他们到底有什么相同和不同呢?
今天大家也要心情愉悦哦!
指针和数组有关系吗?
大家都知道数组和指针在访问方式上都很相似,那么他们之间有关系吗?且听我娓娓道来。
指针形式定义字符串并访问
首先我们用指针定义一个字符串,分别用两种方式访问(指针访问,和【】访问)
const char *p = "holle boy";
int len = strlen(p);
printf("指针形式访问\n");
for (int i = 0; i < len; i++)
{
printf("%c ", *(p + i));
}
printf("\n数组形式访问\n");
for (int i = 0; i < len; i++)
{
printf("%c ", p[i]);
}
可以看出p用哪一种访问方式都可以,那么这可以说明指针和数组有关系吗?(现在还不确定)
另外说下p,这个开辟的字符串是在内存中的字符常量区的,即使没有const 也不可以修改内部的值,因为这是在操作系统级别的保护。在main函数栈帧中存放的是指针变量p的地址,而p的指向是在字符常量区所创建的字符串的首地址处,简略图,供大家参考。
数组形式定义字符串并访问
那么数组形式定义一个字符串,并访问他。
char q []= "holle girl";
int len = strlen(q);
printf("指针形式访问\n");
for (int i = 0; i < len; i++)
{
printf("%c ", *(q + i));
}
printf("\n数组形式访问\n");
for (int i = 0; i < len; i++)
{
printf("%c ", q[i]);
}
这是数组开辟的,并且用两种形式访问的。好像数组也可以用指针形式访问啊,那么指针和数组有关系吗?(还是不确定)
对比两者区别
先讲个小例子吧,假如这个世界上有你的双胞胎,它的身形外貌和你一样,甚至作息都和你一样,你兄弟是和你完全一样吗?
首先你们可能有很多相似的地方,甚至作息相同,但是在本质上,你们是完全不同的两种人格,所以是完全不等价的。
指针和数组这两个就像是双胞胎,他们很像,但是我们不能把它们在概念或者本质上混为一谈。
以上面的例子分析:
这个是数组的存放,是在栈区开辟的空间,所有的字符串的元素都在栈上,并且可以修改值。
都可以用指针和数组形式进行访问。
这个是指针形式的存放开辟的空间,在栈区处存放的是p的地址,而在字符常量区存放的字符串的内容。并且值不可被修改。
这样分析,那么从字符串的存储角度,那么指针和数组是没有一点一点关系,只不过在访问方式上他们有很多相似之处。
得出结论:指针和数组没有关系
数组传参的降维问题
首先我们要知道数组在进行函数调用传参时,会发生降维,降为成指针。
看个例子:
void Show(int arr[] /*int* arr*/, int num)
{
for (int i = 0; i < num; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
int main()
{
int a[5] = { 1, 2, 3, 4, 5 };
int num = sizeof(a) / sizeof(a[0]);
Show(a, num);
return 0;
}
首先,这是把数组元素打印在屏幕上,那么各位注意过没有函数的形参int arr[]和int *arr都可以打印出结果。为什么呢?并且为什么可以int *的指针接收呢?
通过调试可以看出结果:
可以看出arr的类型是int*的表示arr传的是首元素地址,用int*的指针接收没有警告。
这就叫数组传参的降维。
那么为什么要降维呢?
简单来说,就是为了函数调用的效率,降维成指针,就不用拷贝数组了,只用拷贝指针(4个字节)
那么降维成什么呢?
简单来说就是降维成指向内部元素类型的指针。(后续复杂指针讲解细谈)
为什么要指针和数组的访问方式相同。
上面已经说过了数组降维都是降维成指针,那么如果指针和数组访问方式不同,就会发生下面的情况。
void Show(int arr[], int num)
{
printf("指针形式 ");
for (int i = 0; i < num; i++)
{
printf("%d ", *(arr+i));
}
printf("\n");
}
int main()
{
int a[5] = { 1, 2, 3, 4, 5 };
int num = sizeof(a) / sizeof(a[0]);
Show(a, num);
printf("数组形式打印");
for (int i = 0; i < num; i++)
{
printf("%d ", a[i]);
}
printf("\n");
Show(a, num);
return 0;
}
就会导致每次用用数组传参,就要用指针形式,访问数组也要用数组形式,这样就很麻烦,如果这个函数要执行多次,数组也要访问多次,那么就会导致会出错误,这样明显是不太符合使用场景的,所以最后设计时就会把数组和指针的使用方式通用。
本期总结:
首先我们说了指针和数组的在存储上区别,来深度区分指针和数组是没有任何关系的。
接着我们说了数组的降维,为了铺垫数组和指针访问方式为什么相同。
接着我们说了,因为如果指针和数组访问方式不同时,就会导致一些特殊情况下,使用者不方便,增加了错误概率,所以就把它们访问方式一样了。
下期预告:
下期讲解复杂指针的知识。
下期更精彩哦~!~!~!