juliusun.com
第 25/50 节 冥河C语言教程
数组元素引用是通过数组名后面接方括号[]里面的下标来实现。C语言中,数组名表示的是数组首地址,如我们这样定义一个数组:
那么在定义之后,我们写的数组名a代表数组首地址。数组第一个元素的地址也是数组首地址。因此,在进行地址赋值或运行时,我们把&a[0]可以直接简写成a,如:
可以直接简写成:
数组名的是地址,指名变量存储的也是地址。
数组名可以通过方括号[]运算符来访问某元素,指针也可以。指针是通过星号*运算符来访问。
如我要输出a数组下标为5的元素的值可以这样写:
通过指针的写法是:
很好理解了。*p相当于*(p+0),表示从p存储的地址算起,第0个元素的内容,也就是p指向的内容。*(p + 1)表示从p存储的地址算起,第1个指向地址下一个地址。则*(p + N)表示从p存储的地址开始算起,第N个元素的值。
注意,由于运算符优先级关系*p+1表示,p指向的内容加1。会改变p指向的内容。而*(p + 1)表示的p存储的地址第1个元素的内容,不要记混。
当p = a完成赋值后,假设p的值不再改变,且N为整数,*(p + N)就等同于a[N]。数组和指针是可以连通的。
C语言内部,在处理数组下标时,也是通过地址偏移来实现的,如a[5],在内部,把a当作数组首地址,再加上5个元素占用空间的大小,来操作a[5]的值。和指针*(p+5)效果是一样的。现在大家可以理解了为什么C语言数组可以越界访问了吧。数组在内部也当作指针来处理,指针无所谓越界不越界,所以当然数组越界访问当然在语法上也不算错误。
事实上,他们联系不止这么多。指针和数组定义之后,除了数组名代表的地址不能改变外,在进行引用元素时,可以混用,如:
可以写成
同样:
可以写成
上述代码还可写成:
或:
因为在处理数组时,C内部也是通过指针偏移来得到的,所以数组下标从0开始也就很好理解了。数组名是一个内存地址,指针存储的也是内存地址,你可以通过这条规律来推测他们哪些方面可以通用。
再谈谈数组和指针一个不同的地方。当不作用参数时(作为参数时数组和指针联系和区别以后会讲),定义数组和指针,系统分配给他们的空间是不一样的。在32位系统下,指针类型无论指向什么类型,指针类型占用4个字节大小。而数组是每个元素的大小乘以元素个数。这一点可以通过 sizeof运算符 测试一下。
回到指针和数组联系,下面举个例子,用不同的方法实现一个数组元素的输出。
或:
或:
效果类似如下图: