当前位置:嗨网首页>书籍在线阅读

13-使用指针形参

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

10.4.1 使用指针形参

函数要处理数组必须知道何时开始、何时结束。 sum() 函数使用一个指针形参标识数组的开始,用一个整数形参表明待处理数组的元素个数(指针形参也表明了数组中的数据类型)。但是这并不是给函数传递必备信息的唯一方法。还有一种方法是传递两个指针,第1个指针指明数组的开始处(与前面用法相同),第2个指针指明数组的结束处。程序清单10.11演示了这种方法,同时该程序也表明了指针形参是变量,这意味着可以用索引表明访问数组中的哪一个元素。

程序清单10.11  sum_arr2.c 程序

/* sum_arr2.c -- 数组元素之和 */
#include <stdio.h>
#define SIZE 10
int sump(int * start, int * end);
int main(void)
{
     int marbles[SIZE] = { 20, 10, 5, 39, 4, 16, 19, 26, 31, 20 };
     long answer;
     answer = sump(marbles, marbles + SIZE);
     printf("The total number of marbles is %ld.\n", answer);
     return 0;
}
/* 使用指针算法 */
int sump(int * start, int * end)
{
     int total = 0;
     while (start < end)
     {
          total += *start;    // 把数组元素的值加起来
          start++;            // 让指针指向下一个元素
     }
     return total;
}

指针 start 开始指向 marbles 数组的首元素,所以赋值表达式 total += * start 把首元素( 20 )加给 total 。然后,表达式 start++ 递增指针变量 start ,使其指向数组的下一个元素。因为 start 是指向 int 的指针, start 递增 1 相当于其值递增 int 类型的大小。

注意, sump() 函数用另一种方法结束加法循环。 sum() 函数把元素的个数作为第 2 个参数,并把该参数作为循环测试的一部分:

for( i = 0; i < n; i++)

sump() 函数则使用第 2 个指针来结束循环:

while (start < end)

因为 while 循环的测试条件是一个不相等的关系,所以循环最后处理的一个元素是 end 所指向位置的前一个元素。这意味着 end 指向的位置实际上在数组最后一个元素的后面。C保证在给数组分配空间时,指向数组后面第一个位置的指针仍是有效的指针。这使得 while 循环的测试条件是有效的,因为 start 在循环中最后的值是 end [1]。注意,使用这种“越界”指针的函数调用更为简洁:

answer = sump(marbles, marbles + SIZE);

因为下标从 0 开始,所以 marbles + SIZE 指向数组末尾的下一个位置。如果 end 指向数组的最后一个元素而不是数组末尾的下一个位置,则必须使用下面的代码:

answer = sump(marbles, marbles + SIZE - 1);

这种写法既不简洁也不好记,很容易导致编程错误。顺带一提,虽然C保证了 marbles + SIZE 有效,但是对 marbles[SIZE] (即存储在该位置上的值)未作任何保证,所以程序不能访问该位置。

还可以把循环体压缩成一行代码:

total += *start++;

一元运算符++ 的优先级相同,但结合律是从右往左,所以 start++ 先求值,然后才是 start 。也就是说,指针 start 先递增后指向。使用后缀形式(即 start++ 而不是 ++start )意味着先把指针指向位置上的值加到 total 上,然后再递增指针。如果使用 ++start ,顺序则反过来,先递增指针,再使用指针指向位置上的值。如果使用 ( start)++ ,则先使用 start 指向的值,再递增该值,而不是递增指针。这样,指针将一直指向同一个位置,但是该位置上的值发生了变化。虽然 start++ 的写法比较常用,但是 (start++) 这样写更清楚。程序清单10.12的程序演示了这些优先级的情况。

程序清单10.12  order.c 程序

/* order.c -- 指针运算中的优先级 */
#include <stdio.h>
int data[2] = { 100, 200 };
int moredata[2] = { 300, 400 };
int main(void)
{
     int * p1, *p2, *p3;
     p1 = p2 = data;
     p3 = moredata;
     printf("  *p1 = %d,   *p2 = %d,     *p3 = %d\n",*p1, *p2, *p3);
     printf("*p1++ = %d, *++p2 = %d, (*p3)++ = %d\n",*p1++, *++p2, (*p3)++);
     printf("  *p1 = %d,   *p2 = %d,     *p3 = %d\n",*p1, *p2, *p3);
     return 0;
}

下面是该程序的输出:

  *p1 = 100,      *p2 = 100,        *p3 = 300
*p1++ = 100,    *++p2 = 200,    (*p3)++ = 300
  *p1 = 200,      *p2 = 200,        *p3 = 301

只有 (*p3)++ 改变了数组元素的值,其他两个操作分别把 p1p2 指向数组的下一个元素。