C语言中数组名和指针之间的关系非常容易让人混淆,虽然有经验的程序员都能轻松说出它们之间的共同与不同点,不过在实际使用时,程序员还是会常常被这两者坑到。项目组内就有人因为对数组名和指针的使用不当导致出现了硬件复位的重大BUG.
这里列出几种特别让人“拎不清”的情景。
1. 用作函数形参的情况,数组名与指针完全是等价的。
以求数组元素之和的函数为例,我们常用的函数形式是:
int SumArray(int *a, unsigned int
len),对于a,可以用指针的自增解引用操作,亦可用方括号[]下标操作。
其实如果将形参定义为数组名,表面上是数组名的a,其实是指针,可以使用指针的自境与解引用操作。
int SumArray(int a[], unsigned int len)
{
int sum = 0;
for ( int i = 0 ; i < len; i++)
{
sum +=
*(a++); //看上去是数组名的a,可以当作指针来使用
}
return sum;
}
作为函数形参,a[]与*a没有区别。
2. 作为全局变量的数组声明与定义, 指针与数组之间有区别。
考虑在文件A.c中定义一个全局的数组ARRAY:
int ARRAY[3] = {1,2,3};
在文件A.h中声明这个全局数组:
extern int *ARRAY;
然后在主文件中使用全局数组ARRAY
int main()
{
printf("%d\n", ARRAY[0]); //编译OK,出现运行时错误,程序异常中止
return 0;
}
这段程序是可以正常编译的,但在运行时却异常中止,程序出现运行时错误。
将声明改正为:
extern int ARRAY[],
程序才能正常运行。这提示我们:在声明全局数组时,数组名声明和指针声明两者之间是有区别的,只能用
ARRAY[],而不能用*ARRAY,否则会导致不可预测的运行时错误。
3. 两个文件中两个全局数组同名的情况。
文件A.c中定义数组:
int ARRAY[100];
文件B.c中定义数组:
int ARRAY[200];
则必然出现变量重复定义的错误,不能编译通过。
在B.c中的定义前面加上extern,使定义变成声明:
extern int
ARRAY[200],则能够顺利编译,此时方括号的200有迷惑性,这个数字不起任何作用,与空的方括号的效果是一样的,数组大小由A文件定义时决定。
如果A文件中的ARRAY定义也加上extern,
那么两个.c文件中的定义都变成了声明,那么将出现链接时错误,提示无法找到外部变量。
如果在A文件中的ARRAY 加上extern 同时又进行显式初始化:
extern int ARRAY[3] = {1,2,3};
那么这里的声明又转化为了定义,程序可正常编译、链接和运行了。