C语言的语法简单,规则并不复杂,因此很多初学者在刚开始接触C语言时,常常会产生“C语言不过如此”的感觉。不过这种感觉一般只会持续到C语言的“指针”语法之前,之后便会被各种指针概念(指针,指针的指针,数组指针,指针数组等)弄昏了头。
“数组指针”能为C语言程序带来什么好处?
C语言的指针语法本身并不难,但是其衍生出的“各种指针”常使很多初学者迷惑不已,曾经不止一个读者问我“指针数组”和“数组指针”的区别。不过经常看我文章的朋友应该能够随口指出二者的区别:“指针数组”是存放指针元素的数组,是数组。而“数组指针”是数组类型的指针,是指针。
但是,不知道读者想过没有,C语言程序开发中,“数组指针”的意义到底是什么呢?明明一般的指针就足够使用了,为何还要使用这样令人迷惑的指针呢?
在C语言程序开发中,程序员可以定义这样的指针:
char (*p)[10];
分析这行C语言代码是简单的,() 的优先级较高,因此 *p
首先说明它是一个指针,剩余的 char [10]
则说明 p 是一个 10 字节数组类型的指针。换言之,指针 p 指向一个拥有 10 个 char 类型元素的数组。
像这样声明指针 p 的好处是,如果尝试将一个其他长度(不是10字节)的数组地址赋值给 p 时,编译时就会给出警告信息。下面是一段测试C语言代码,请看:
int main()
{
char (*p)[10];
char arr[5];
p = &arr;
return 0;
}
编译这段代码,会得到一段指针类型不匹配的警告信息:
稍稍有些开发经验的C语言程序员应该都定义过下面这样的函数:
void fun(char *p, int len);
参数 len 用于描述指针 p 索引的内存长度,这样的定义方式显然无法保证传递给 fun() 函数的内存长度等于期望值。假如 fun() 函数的开发者期望传递给 fun() 函数的指针 p 索引的内存长度为 10,那么只能寄希望于他的同事严格遵守开发者的意图(这并不容易),毕竟
fun(p, 9);
fun(p, 110);
都是合法的,这样的函数调用编译器不会产生任何错误或者警告信息。如果 fun() 函数采用数组指针的方式定义,情况就不同了,相关C语言代码如下:
void fun(char (*p)[10]);
这样的定义方式强制 fun() 函数的调用者传递索引指定长度内存的指针,否则编译器将发出警告或者错误信息。
这看起来很有用,但是真的如此吗?
要得到答案,最简单直接的方法就是实验。为此,我们编写下面这样的C语言代码,请看:
void fun(char (*p)[10])
{
//...
}
int main()
{
char arr_5[5];
char arr_10[10];
fun(&arr_5);
fun(&arr_10);
return 0;
}
编译并执行这段C语言代码,得到如下输出,请看:
与预期一致,在将长度为 5 的 arr_5 作为参数传递给 fun() 函数时,编译器发出了警告信息,这样一来,C语言本身就会提醒程序员修改代码,遵守 fun() 函数期望得到的内存长度。
最后
可见,C语言程序开发中,数组指针是有其独特的作用的,它可以用于限制函数接收指针索引的内存长度,利用编译器规范程序项目。另外值得说明的是,在定义数组指针时,利用C语言的typedef关键字常常能够使代码更加易读:
typedef int Vector3d[3];
void transform(Vector3d *vector);
/* equivalent to `void transform(int (*vector)[3])` */
...
Vector3d vec;
...
transform(&vec);
谢谢,终于有点明白了,之前一直在想这个到底有什么用,也在理解数组指针
算是找到一点,约束,有点意义了