C语言小妹不懂指针和数组的关系?那就安排指针数组关系详解
Posted 攻城狮白玉
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言小妹不懂指针和数组的关系?那就安排指针数组关系详解相关的知识,希望对你有一定的参考价值。
目录
前言
前段时间整理的C语言的一些基础知识,给到我家小妹复习用的。
有整体入门基础文章——【C语言】拯救新手,半小时从零到一认识C语言基础
还有C语言数据类型的详解——【C语言】数据类型一文详解
问了下她,还需要什么,她说要字符指针跟数组的,那这期就安排C语言指针类型的详解
关于数组和指针的一些定义的介绍和使用,我在【C语言】数据类型一文详解一文中有提到。为了方便这次数组和指针的应用详解,这里咱们简单复习一下。
一、什么是数组
数组可以看作是一系列相同类型变量的一个集合,而这个集合的名称就叫数组名。
比如上面的例子,咱们可以声明一个数组来代替
int i_baiyu[5] = {1,2,3,4,5};//baiyu 就是数组名,这里是声明了一个长度为5的int型数组
所有的数组都是由连续的内存位置组成。最低的地址对应第一个元素,最高的地址对应最后一个元素。
请注意上面提到的连续内存的位置,也就是说,数组元素的地址是连续的。
二、什么是指针
指针是一种特殊的变量类型。
每一个变量都有一个内存位置,每一个内存位置都定义了可使用 & 运算符访问的地址,它表示了在内存中的一个地址。而指针则是指向了这个变量所在的内存地址。
这样子可能不太好理解,咱们举个例子
比如:baiyu是住在贝克街221号B,那么baiyu(变量)所住的地方(内存),而门牌号(指针)贝克街221号B(内存地址)
指针就是相当于咱们的门牌号,指向的是内存所在的地址。指针变量是用来存放内存地址的变量。
指针变量的声明格式如下:
数据类型 *指针变量名
这里的数据类型跟咱们前面提到的数据类型是一致的,也就是int、char、double、float这些
回到小妹的提问,字符型指针,那其实就是用char关键字定义的指针
char *c_baiyu_p = NULL;//定义一个字符型指针,并赋值为空NULL
三、指针变量的大小
我在【C语言】数据类型一文详解一文中有提到,C 语言里有六种基本数据类型,分别用short、int、long、char、float、double 这六个关键字表示。这六种类型分别占用的内存空间不一样。通过sizeof函数,咱们知道了,char 型变量占 1 字节、short型变量占2个字节、int 型变量占 4 字节,long型变量个字节、占float 型变量占 4 字节、double 型变量占 8 字节。
同样的,想要知道不同类型的 指针变量占用多少内存空间,咱们也一样可以用sizeof函数来获取。
#include<stdio.h>
int main() {
int* i_baiyu_p = NULL; /* 一个整型的指针 */
char* c_baiyu_p = NULL; /* 一个字符型的指针 */
double* d_baiyu_p = NULL; /* 一个 double 型的指针 */
float* f_baiyu_p = NULL; /* 一个浮点型的指针 */
printf("指针 i_baiyu_p 的大小为:%d\\n", sizeof(i_baiyu_p));
printf("指针 c_baiyu_p 的大小为:%d\\n", sizeof(c_baiyu_p));
printf("指针 d_baiyu_p 的大小为:%d\\n", sizeof(d_baiyu_p));
printf("指针 f_baiyu_p 的大小为:%d\\n", sizeof(f_baiyu_p));
return 0;
}
从输出结果可以看出,所有的类型的指针变量大小都是占4个字节,并不像普通变量一样,根据数据基类型不一样而对应的内存大小不一样。因为指针变量存放的都是数据的内存地址。
四、数组和指针的关系
上面咱们说到,定义了数组之后,数组元素的内存空间是连续的。口说无凭,上代码
#include <stdio.h>
int main() {
int i_baiyu[5] = {1,2,3,4,5};
int i = 0;
for (i = 0; i < 5; i++)
{
printf("i_baiyu[%d]的地址是:0x%p\\n",i, &i_baiyu[i]);
}
printf("i_baiyu的地址是:0x%p\\n",i_baiyu);//注意这里不用取地址符&
return 0;
}
根据打印出来的信息,我们可以看到,数组元素的内存地址是连续的。而且数组名的地址跟数组的第一个元素的地址是相同的,也就是说,数组名是指向数组的第一个元素。
PS:小伙伴们在实验过程中可能会发现打印出来的地址跟我不一样,这是没关系的,因为每次程序都会重新向内存申请一块区域来存放数据。关于内存这一块,后面我会写一篇文章专门来讲~
数组数据在内存的存储关系图如下:
既然如此,我们是不是就可以直接通过指针来访问数组元素了呢?答案是肯定的。
我们可以通过对指针进行运算,让指针进行移动。
C 语言规定:如果指针变量 p 已经指向一维数组的第一个元素,那么 p+1 就表示指向该数组的第二个元素。
咱们直接上代码可能好理解一些:
#include <stdio.h>
int main() {
int i_baiyu[5] = { 1,2,3,4,5 };
int i = 0;
int* i_p = i_baiyu;// 数组名赋值给指针 i_p
int* i_q = &i_baiyu[0];// 数组第一个元素的地址赋值给 i_q
printf("----\\n");
for (i = 0; i < 5; i++)
{
printf("i_baiyu[%d]的地址是:0x%p,对应元素的值是:%d\\n", i, &i_baiyu[i],i_baiyu[i]);
printf("指针i_p的地址是: 0x%p,指向的值是:%d\\n", (i_p + i), *(i_p + i));
printf("指针i_q的地址是: 0x%p,指向的值是:%d\\n", (i_q + i), *(i_q + i));
printf("----\\n");
}
return 0;
}
(i_p + i) 得到的是对应数组元素的指针地址
*(i_p + i )得到的是对应数组元素的指针地址指向的值
从上面这个例子可以看出,数组名就是指向了数组的首个元素的地址。
五、指针变量的自增自减运算
这两天刚解决了粉丝关于普通变量的自增自减运算符的疑问,有需要的同学可以戳链接
【C语言】一文弄通++i,i++,i--,--i,解决粉丝疑问
没错,咱们可爱的指针变量也有这种运算操作惊不惊喜,意不意外。
前面说过,i_p+i表示指向数据的第i个元素。当i等于1时,i_p = i_p+1可以写成 i_p++。是不是很熟悉,这里的加加减减运算符的用法跟普通变量的自增自减是一样的。
给段代码让大家熟悉一下。
#include <stdio.h>
int main() {
int i_baiyu[5] = { 1,2,3,4,5 };
int i = 0;
int* i_p = i_baiyu;// 数组名赋值给指针 i_p
printf("----\\n");
for (i = 0; i < 5; i++)
{
printf("指针i_p的地址是:0x%p,指向的值是:%d\\n", (i_p), *(i_p++));
printf("----\\n");
}
return 0;
}
六、两个参数确定一个数组
根据上面咱们讲到的,数组名指向数组的首地址(第一个元素的地址),通过数组长度对指针进行加(减)运算,从而可以得出一个完整的数组的数据内容。因此当我们把数组作为参数,在函数间传递数组时,可以在形参定义一个指针变量用于接收数组名,以及定义一个整型数据用于接收数组长度。
上代码示例
#include<stdio.h>
void outputArr(int* i_arr, int i_arr_length) {
int* i_p = i_arr;
printf("数组的值为:");
for (; i_arr < i_p + i_arr_length; i_arr++) {
printf("%d ", *i_arr);
}
printf("\\n\\n");
}
int main() {
int i_baiyu[] = { 1,2,3,4,5 };
int i_baiyu_2[] = { 111,222,333,444,555,666,777 };
outputArr(i_baiyu, 5);
outputArr(i_baiyu_2, 7);
return 0;
}
七、字符型指针和字符型数组
回到小妹提给我的问题,其实通过前面六点的解释应该可以明白指针与数组之间的关系。而字符型指针和字符型数组只是指针和数组里的一个子类
相同的点,这里就不再赘述。这里讲一下字符型数组一些要注意的地方。
- 在字符型数组的时候,可以直接通过字符数组元素进行修改赋值。在字符型指针赋值字符串常量之后,不可以通过指针指向某个元素修改值。
- 字符数组名是常量,故数组名不能++;字符指针是个变量,故指针可以++;
给一个示例代码
#include<stdio.h>
int main() {
char c_baiyu[] = "https://blog.csdn.net/zhh763984017";
int i;
for ( i = 0; i < 35; i++)
{
printf("%c", *(c_baiyu + i));
}
printf("\\n");
char* c_baiyu_p = "zhh_baiyu";//字符型指针也可以直接赋值为字符串常量
c_baiyu[0] = '6';//因为c_baiyu是数组,所以元素的值可以修改
//*(c_baiyu_p +1) = '6';//取消注释报错,这里是字符型指针指向的值,不可以修改
printf("%s\\n", c_baiyu);
printf("%s\\n", c_baiyu_p);
}
总结
本文简单阐述了数组和指针之间的关系。每一个变量都有一个内存位置,每一个内存位置都定义了可使用【&】运算符访问的地址,指针表示了在内存中的一个地址。访问指针变量中可用地址的值,通过取值运算符【*】将指针变量里地址对应的变量值取出这个操作也被叫做解引用。
数组则是定义了一系列相同类型的变量,这些变量在内存地址上是连续的,因此咱们可以通过指针运算偏移的方式来读取对应的数组的值。
写在最后
如果觉得本文对你有帮助的话,麻烦一键三连支持一下攻城狮白玉,你的一个小小的三连是我创作的无限动力。
如果有想看的内容,也可以在博文底部评论,我会整理出来给到大家~
以上是关于C语言小妹不懂指针和数组的关系?那就安排指针数组关系详解的主要内容,如果未能解决你的问题,请参考以下文章