C语言——理解指针和数组

首先我们举一个变相使用指针的例子:数组名是数组首元素的地址。也就是说,如果a是一个数组,下面语句成立:

a == &a[0]; //数组名是该数组首元素的地址

a和a[0]都表示数组首元素的内存地址。两者都是常量,在程序的运行过程中,不会改变。但是,可以把它们赋给指针变量,然后可以修改指针变量的值。如下面程序:

#include<stdio.h>
#include<stdlib.h>
#define size 4
int main() {
 short dates[size];
 short *pti;
 short i;
 double bills[size];
 double *ptf;
 pti = dates;//把数组地址赋给指针
 ptf = bills;
 printf("%23s %10s\n", "short", "double");
 for (i = 0; i < size; ++i) {
  printf("pointers + %d: %10p %10p\n", i, pti + i, ptf + i);
 }
 system("pause");
 return 0;
}

运行结果:
在这里插入图片描述
注:地址是十六进制的,因此7D比7C大1,3D比3C大1。
在我们的系统中,地址按字节编址,short类型占用2字节,double类型占用8字节。在C中,指针加1指的是增加一个存储单元。对数组而言,这意味着加1后的地址是下一个元素的地址,而不是下一个字节的地址。这是为什么必须声明指针所指向对象类型的原因之一。只知道地址不够,因为计算机要知道存储对象需要多少字节(即使指针指向的是标量变量,也要知道变量的类型,否则*pt就无法正确地取回地址上的值)

现在可以更清楚地定义指向int的指针,指向float的指针,以及指向其他数据对象的指针。

  • 指针的值是它所指向对象的地址。地址的表示方法依赖于计算机内部的硬件。许多计算机都是按字节编址,意思是内存中的每个字节都按顺序编号。这里,一个较大的对象的地址(如double类型的变量)通常是该对象第一个字节的地址。
  • 在指针前面使用*运算符可以得到该指针所指向对象的值。
  • 指针加1,指针的值递增它所指向类型的大小(以字节为单位)。

下面的等式体现了C语言的灵活性:

 dates + 2 == &dates[2];//相同的地址
 *(dates + 2) == dates[2];//相同的值

以上关系表明了数组和指针的关系十分密切,可以使用指针标识数组的元素和获得元素的值。从本质上看,同一个对象有两种表示法。实际上,C语言标准在描述数组表示法时确实借助了指针。也就是说,定义ar[n]的意思是*(ar+n)。

明白了数组和指针的关系,便可以在编写程序时适时使用数组表示法或指针表示法。如下面程序:

#include<stdio.h>
#include<stdlib.h>
int main() {
 int days[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
 int i = 0;
 for (i = 0; i < 12; ++i) {
  printf("Month %2d has %d days.\n", i + 1, *(days + i));//与days[i]相同
 }
 system("pause");
 return 0;
}

这里,days是数组首元素的地址,days+i是元素days[i]的地址,而*(days+i)则是该元素的值,相当于days[i]。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值