数组不等于指针

引论

C语言中有一种说法叫做“指针和数组等价”,在很多情况下,我们感觉确实如此,比如说对数组的引用总是可以写成对指针的引用,指针和数组名在一定意义上可以互用。但是作为一门高度精炼的语言(纯属个人感觉),如果指针和数组真的等价的话,那么c语言就真真没有必要设计这样两个名词了。看下面的例子:

1
2
3
4
//file1  
int a[10];
// file2
extern int *a;

这里,在file1中定义了一个数组,在file2中我们要用到file1中的外部变量a[10]的话,要事先声明,因此有了

int *a;``` 但是如果真要这样做的话,编译器肯定会报错,这是为什么呢?因为数组和指针是不相等的。
1
2
3
4
5
6
7
8
9
10



# 数组和指针的访问

要解决上面的问题,首先我们要先明白数组和指针是如何访问的。

定义了变量后,编译器为每个变量分配了一个地址,这个地址在编译时可知,但是存储在变量中的值只有在运行时才是可知的。

对于数组,定义以及初始化得到

char a[4]=”bcd”;

1
2
3
要访问a[3],则编译器首先找到a的地址,然后取(a的地址+3)的内容。

而对于指针,定义和初始化后,得到

char *p = “bcd”;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
要访问p[3],则编译器会首先得到地址p的内容,把它作为字符的地址开始,然后取(地址+3)的内容。

因此当我们定义了一个数组,却声明成为了一个指针时(上面的例子所示),那么编译器的做法是:

(1): 编译器找到地址为a的内容即a[0],这是字符‘b’,但是编译器却认为它是地址

(2): 把(1)中的’b’作为字符的地址起始

(3): 取(地址起始+i)的内容。

也就是说,如果把a声明成指针的话,无论a定义为数组还是指针,都会按照这三个步骤走。因此如果a定义为指针的话,是没有问题的,但是a如果定义为数组,就会出错。

因此声明和定义用到严格匹配。



# 指针和数组的其他区别


| 指针 | 数组|
| :-------- | -------- |
| 保存数据的地址| 保存数据|
| 间接访问数据 | 直接访问数据|
| 常用于动态数据结构| 通常用于固定数目切类型相同的元素|
| 相关函数Malloc(),free() | 隐式分配和删除|
| 指针是变量 | 数组名不是变量|


指针与数组的初始化

指针和数组都给可以在定义时用字符串进行初始化

char *a = “bcd”;
char a[] = “bcd”

1
2
3
但是初始化指针所创建的字符串是只读的,通过指针进行修改的话,程序会出现未定义的行为,而通过数组可以方便的修改字符串的值。

当然这样对指针初始化只有对字符串常量有效,而不可以对浮点型等常量如此,如

float*p = 3.14 //wrong
```

显示 Gitment 评论