C语言的数组指针能带来什么好处?为什么要使用它?

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);
阅读更多:   C语言
添加新评论

icon_redface.gificon_idea.gificon_cool.gif2016kuk.gificon_mrgreen.gif2016shuai.gif2016tp.gif2016db.gif2016ch.gificon_razz.gif2016zj.gificon_sad.gificon_cry.gif2016zhh.gificon_question.gif2016jk.gif2016bs.gificon_lol.gif2016qiao.gificon_surprised.gif2016fendou.gif2016ll.gif