定义成数组,声明成指针与定义成指针,声明成数组带图详解

在理解定义成数组,声明成指针与定义成指针,声明成数组之前,我们需要知道:
(1)数组就是数组,指针就是指针,虽然在用法上相似,但是他们的实际意义完全是两回事。

char arr[]="abcdef";
char *p=arr;

arr和p都可以通过指针的方式和下表的方式访问字符串”abcdef”;但是他们的意义却不一样。如图所示
这里写图片描述

(2)关于定义和申明的区别,即定义为变量分配了内存,而申明没有;定义只能出现一次,而申明可以出现多次。extern告诉编译器arr这个名字已经在别的文件中被定义了,代码中使用的arr是在别的文件中定义的。

(3)对于编译器来说,如果他需要读取某个地址(可能还需要加上偏移量)来进行某种操作,他就可以通过“开锁动作”直接读\写这个地址上的内存。但是,对于指针而言,必去先找到存储这个地址的地方,取出这个地址值然后对这个地址进行“开锁动作(即解引用)”,然后才能访问内存。

1.定义成数组,声明成指针

cpp1:

char arr[] = "abcdef";
cpp2:

#include<stdio.h>
#include<stdlib.h>

extern char *arr;

int main()
{
    printf("%x\n", arr);
    // printf("%s",(char *)&arr );
     system("pause");
     return 0;
}

这里写图片描述

在文件1中,arr被定义成字符数组,在文件2中,声明arr为指向字符的指针变量。
在64\32位系统,vs平台下,指针变量占4个字节,编译器会把存储在指针变量中的任何值都当做地址来处理。所以,如果需要访问字符串”abcdef”,必去先从指针变量中取出其保存的地址。但是,对于cpp2中的指针arr保存的是什么呢?如下图:

这里写图片描述
(1)编译器取出前4个字节空间的值,转换成十六进制0x64636261(不考虑大小端存储)。
(2)地址0x64636261上的内容按照char类型读写。但是地址0x64636261有可能不是有效的地址,或者是有效地址,但并不是我们想要的。

那么,我们到底怎样输出字符串“abcdef”呢?这里就要用到简单粗暴的方式了,哈哈,就是我们的强制类型转换。正确的输出语句:printf(“%s”,(char *)&arr );就可以输出字符串“abcdef”。

2.定义成指针,声明成数组

cpp1:
char *arr = "abcdef";
cpp2:

#include<stdio.h>
#include<stdlib.h>

extern char arr[];

int main()
{
    printf("%s\n", arr);
    system("pause");
    return 0;
}

这里写图片描述

在cpp1中,编译器为指针变量arr分配4字节的空间,保存了字符串“abcdef”首字符的首地址,并且这个字符串本身保存在内存的静态区,其内容不能修改。在cpp2中,编译器认为arr是一个数组,数组内保存的是char类型的数据,那么具体是什么内容呢?如图所示:
这里写图片描述

编译器把arr当做一个包含4个char类型数据的数组使用,按照char类型取出arr[0]、arr[1]、arr[2]、arr[3]的值0x00、0x00、0x00、0x10,。但这并非我们需要的那块内存的的数据。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值