C专家编程(4)

数组与指针

在大部分情况下,数组和指针是可以互换的。书中的第4章主要讲解了数组和指针的不同之处,而在第9章则着重讨论两者可以互换的场景。

不同之处

对于两者的不同之处,主要在于访问两者时有一些不同。

编译器会为每个变量分配一个地址,每个符号的地址在编译时可知(如数组的名字)。那么在访问数组中的数据时,可以通过符号表直接得出数组的起始地址,加上偏移量即可访问对应的数据。

而对于指针,必须先在运行时取得它当前存储的值,再对它解引用来获取(数组的)起始值,最后才能加上偏移量来访问数据。


其他区别

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

相同之处

在书中,主要从“声明”和“使用”两种情况下进行讨论,直接看图:

在C语言标准中,有若干条规则对两者间的联系进行了说明,本书作者对其进行了进一步的说明:

  1. “表达式中的数组名”就是指针
  2. C语言把数组下标作为指针的偏移量
  3. “作为函数参数的数组名”等同于指针

编程挑战

#include <stdio.h>

#define PR(fmt,val) printf(#val " = %" #fmt "	", (val))
#define NL putchar('
')

#define PRINT1(f,x1) PR(f,x1), NL
#define PRINT3(f,x1,x2,x3) PR(f,x1), PRINT2(f,x2,x3)

static void func1(char ca[]) { PRINT3(#x, &ca, &(ca[0]), &(ca[1])); }

static void func2(char* pa)
{
  PRINT3(#x, &pa, &(pa[0]), &(pa[1]));
  PRINT1(#x, ++pa);
}

char ga[] = "abcdefg";

int main()
{
  PRINT3(#x, &ga, &(ga[0]), &(ga[1]));
  func1(ga);
  func2(ga);
  return 0;
}

运行结果如下:

&ga = 0x37c3b010        &(ga[0]) = 0x37c3b010   &(ga[1]) = 0x37c3b011
&ca = 0x7f38c918        &(ca[0]) = 0x37c3b010   &(ca[1]) = 0x37c3b011
&pa = 0x7f38c918        &(pa[0]) = 0x37c3b010   &(pa[1]) = 0x37c3b011
++pa = 0x37c3b011

可以看出作为参数,数组的地址和数组的第一个元素的地址是不同的。

原文地址:https://www.cnblogs.com/maxiaowei0216/p/14247509.html