C语言:指针和数组

指针提供一种以符号形式使用地址的方法。因为计算机的硬件指令非常依赖地址,指针在某种程度上把程序员想要传达的指令以更接近机器的方式表达。因此,使用指针的程序更有效率。尤其是,指针能有效地处理数组。我们很快就会学到,数组表示法其实是在变相地使用指针。

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

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

flizny&flizny[0] 都表示数组首元素的内存地址(&是地址运算符)。两者都是常量,在程序的运行过程中,不会改变。但是,可以把它们赋值给指针变量,然后可以修改指针变量的值,如程序清单10.8所示。注意指针加上一个数时,它的值发生了什么变化(转换说明%p通常以十六进制显示指针的值)。

#include

#define SIZE 4

int main()
{
  short dates[SIZE];
  short * pti;
  short index;
  double bills[SIZE];
  double * ptf;
  pti = dates; //把数组地址赋给指针
  ptf = bills;
  printf("%23s %15s\n", "short", "double");
  for(index=0; index<SIZE; index++)
    printf("pointers + %d: %10p %10p\n", index, pti+index, ptf+index);
  return 0;
}

下面是该例的输出示例:

第2行打印的是两个数组开始的地址,下一行打印的是指针加1后的地址,以此类推。

我们的系统中,地址按字节编址,short 类型占用2字节,double 类型占用8字节。在C中,指针加1指的是增加一个存储单元。对数组而言,这意味着把加1后的地址是下一个元素的地址,而不是下一个字节的地址(见图)。这是为什么必须声明指针所指向对象类型的原因之一。只知道地址不够,因为计算机要知道储存对象需要多少字节(即使指针指向的是标量变量,也要知道变量的类型,否则 *pt  就无法正确地取回地址上的值)。

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

指针的值是它所指向对象的地址。地址的表示方式依赖于计算机内部的硬件。许多计算机(包括PC和Macintosh)都是按字节编址,意思是内存中的每个字节都按顺序编号。这里,一个较大对象的地址(如 double 类型的变量)通常是该对象第一个字节的地址。

在指针前面使用 * 运算符可以得到该指针所指向对象的值。

指针加1,指针的值递增它所指向类型的大小(以字节为单位)。

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

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

以上关系表明了数组和指针的关系十分密切,可以使用指针标识数组的元素和获得元素的值。从本质上看,同一个对象有两种表示法。实际上,C语言标准在描述数组表示法时确实借助了指针。也就是说,定义 ar[n] 的意思是 *(ar + n) 。可以认为 *(ar + n) 的意思是“到内存的 ar 位置,然后移动 n 个单元,检索储存在那里的值”。

顺带一提,不要混淆  *(dates+2) *dates+2。间接运算符(*)的优先级高于+,所以 *dates+2 相当于 (*dates)+2 。
*(dates + 2) // dates第3个元素的值
*dates + 2  // dates第1个元素的值加2

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

 收藏 (0) 打赏

您的赞助是我分享的最大动力!

支付宝扫一扫赞助

微信钱包扫描赞助

转载请注明出处:STBLOG » C语言:指针和数组

分享到: 更多 (0)

热门文章

  • 评论 抢沙发

    评论前必须登录!

    立即登录   注册

    ❤ 感谢您的关注与支持!❤

    对TA表白给我留言
    我要注册

    登录

    忘记密码 ?

    您也可以使用第三方帐号快捷登录

    切换登录

    注册

    我们将发送一封验证邮件至你的邮箱, 请正确填写以完成账号注册和激活