[0] 数组和指针的前世今生

为什么不能运行?

//文件1
int mango[100];
//文件2
extern int *mango;
//开始使用指针访问文件1中的数组

上面的例子是类型不匹配错误,无法正常运行,错误和下面的例子相似

//文件1
int mango;
//文件2
extern float *mango;

声明和定义的区别

  • 定义有且只有1个,但它可以有多个extern声明
  • 定义是特殊的声明,它分配了内存空间,用于创建新的对象,声明则用于指代其他地方定义的对象
  • 注意多维数组声明的时候,要给出除最左边一维之外的其他维的长度

可修改的左值

  • 出现在赋值号左边的称为左值,右边的称为右值
  • 左值代表的是地址,右值代表的是地址的内容
  • 左值编译时可知,右值运行时才知道,编译器为每个变量分配一个地址,这个地址编译时可知,而且该变量在运行时一直保存于这个地址。相反,右值运行时才知道,如果需要用到右值,编译器就发出指令从指定的地址读取变量值放入寄存器
  • 左值一般都是可修改的,那么为什么会有不可修改的左值,数组名就是不可修改的左值,可以简单理解为数组名的左值永远都只能是首地址
    这里写图片描述

数组的访问

这里写图片描述

指针的访问

这里写图片描述
这里写图片描述

开篇的错误解释

对于extern int * mango; 当用mango[2]来访问的时候,首先,会按照图B所示对指针解引用,然后按照图A对下标进行偏移并直接访问,更为正式的说法:
1、取得mango的地址,提取存储于此处的指针;
2、把下标所表示的偏移量与指针的值相加,产生一个地址;
3、访问上面的地址,得到int

  • 因此,既然mango声明为指针,那么不管在定义的时候是数组还是指针,都会按照上述步骤进行指针的下标操作,但是只有定义也为指针的时候,才能得到正确的值。
  • 解决的办法很简单,让外部声明和定义互相匹配即可

指针与数组的其他区别

指针数组
保存数据的地址保存数据
间接访问数据,首先取得指针的内容,把它作为地址,然后从这个地址提取数据。如果有一个下标[i],就把指针的内容加上i的偏移作为地址,从中提取数据直接访问数据,a[i],只是简单的访问a+i的地址取得数据
通常用于动态数据结构通常用于存储数目固定且数据类型相同的元素
相关的函数malloc/free隐式分配和删除
通常指向匿名数据自身即为数据名

关于常量字符串

char* p = "abcdef";
int *pn = 2;//ERROR
char a[] = "abcdef"

数组和指针都可以在定义中使用常量字符串初始化,机制却不一样。定义指针时,编译器只是给指针本身分配空间,除非在定义的时候赋值一个常量字符串进行初始化。只有常量字符串才可以如此,浮点数之类绝对不行。
ANSI C规定,初始化指针时的常量字符串为只读,如果试图通过指针改变字符串的值,会出现未定义的行为。
与指针相反,由常量字符串初始化的数组是可以修改的。

Reference

C专家编程

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值