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

来源:互联网 发布:淘宝店铺层级怎么算 编辑:程序博客网 时间:2024/06/05 05:58

在理解定义成数组,声明成指针与定义成指针,声明成数组之前,我们需要知道:
(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,。但这并非我们需要的那块内存的的数据。

0 0