C 学习笔记 - 指针(二):指针和数组 (上)
今天有点累,没有什么精神,也很疲惫,大脑也不受控制。但是早晨起来还是看了点书和资料,把今天理解的总结一下吧!
今天主要看了指针和数组的一些知识点和简单的用法,当然只是一维数组。
之前对数组和指针都有一个大概的认识,但是都很浅显,今天来小小的深入一下数组和指针的学习!
例如:int a[3];
这是一个整数数组,可以包含 3 个元素。通常,我们都是通过 "数组名" 与 "下标" 来使用数组的。包括我之前在 C# 中也是一样!
可是今天的学习,真是令我恍然大悟:原来所谓的数组是由指针而来的。我很开心,因为这都是我之前不知道的,我又有了收获!^_^
在上面的示例中,a[0] 表示数组 a 的第一个值,a[2] 表示数组的最后一个值,也就是第三个值。然而不管是 a[0] 还是 a[2] 他们的类型都是 int(整型)。
那 a 的类型又是什么呢?通常我们都会说 a 是一个整数数组!呵呵,我想只要学过编程的童鞋们都知道。但,其根本并非如此。
在 c 语言中,所有使用数组名的表达式中,数组名的值都是一个指针常量,也是该数组第一个元素的地址!
所以,a 的类型就是 "指向 int 的常量指针",a 的值就是 a[0] 在内存中的地址。需要注意的是:a 是一个指针常量,而非指针变量。
我们不能修改指针常量的值,书上是这样说的:
指针常量所指向的是内存中数组的起始位置,如果修改这个指针常量,唯一可行的操作就是把整个数组移动到内存中的其它位置。但是在程序完成连接之后,内存中的数组位置是固定的,所以当程序运行时,再想移动数组就为时已晚了。因此数组名的值就是一个指针常量。
我们再来看一个例子:写一个函数,让它输出指定数组的元素
1 # include <stdio.h>
2
3 void printIntArrayElements(int *, int);
4
5 int main(void)
6 {
7 int a[4] = {0, 1, 2, 3};
8 int b[6] = {0, 1, 2, 3, -4, -5};
9 int c[8] = {10, 11, -10, -11, 12, 13, -12, -13};
10
11 //此处将 a 和 此数组元素的个数 传给了 printIntArrayElements 函数,
12 //在上文说过,a 的值是一个指针变量,也是数组第一个元素在内存中的地址,
13 //所以实际上是将数组的初始元素的地址传给了 printIntArrayElements 函数。
14 printIntArrayElements(a, 4);
15
16 printIntArrayElements(b, 6); //原理同上
17
18 printIntArrayElements(c, 8); //原理同上
19
20 return 0;
21 }
22
23 void printIntArrayElements(int * intArray, int arrayLength)
24 {
25 int i;
26
27 for(i = 0; i < arrayLength; ++i)
28 {
29 //此处,intArray 是一个指针变量,接收的是数组初始元素的地址,
30 //所以无论是使用数组名与下标,还是 *(intArray + i),在这个循环中它们都是依次指向数组中的元素
31 //所以 数组名[i] 永远等价于 *(intArray + i),但是后者效率更高、速度更快
32 printf("%d ", *(intArray + i));
33 }
34 printf("\n");
35 }
我想仔细看完这个例子大家就应该能明白指针与数组(一维数组)之间的关系了吧!
重要的是:理解数组名的含义,还有下标和元素指针的关系。
在上面的例子中说到:数组名[i] 永远等价于 *(intArray + i),但是后者效率更高、速度更快
那为什么后者的效率更高、速度更快呢?我将会在下一篇文章中详细说明。^_^