c语言入门23,一文弄懂为什么要使用指针,看完还不懂,你踢我

前面几节介绍了 C 语言中指针,也讨论了数组指针指针数组的区别,但归根结底,至今我们说的都是基础数据类型定义的指针,C 语言有复合数据类型,那么它有复合数据类型的指针吗?答案是肯定的,事实上,在 C 语言中复合类型指针的使用相当广泛。

先来看看结构体指针。还是从实例出发,我们首先定义一个结构体类型,它有两个成员变量,分别是 sleep_time(睡觉时间) 和 work_time(工作时间),然后定义这种类型的变量和指针:

struct week{
    double    sleep_time;
    double    work_time;
};
struct week w;
struct week *pw = &w;

可以通过结构体指针 pw 访问 week 结构体的成员:

(*pw).sleep_time = 7.0;

这样写有点麻烦,因此 C 语言非常贴心的提供了“->”运算符,所以我们还可以这样通过结构体指针访问成员:

pw->sleep_time = 7.0;

为什么要使用 C 语言中的指针

好了,现在我们已经知道 C 语言中的结构体指针怎么使用了,铺垫完了。但是,明明使用结构体变量 w 就能很好的读写 week 结构体啊,为什么要用结构体指针呢?这不是麻烦了吗?

为什么要使用结构体指针,其实可以延伸到“为什么要使用指针”,本节将以结构体指针为例讨论一下这个问题。

是的,仅仅访问 week 的 sleep_time 成员,只使用结构体变量 w 就足够了,这时再通过 pw 访问真的麻烦了。但是工具会不会带来方便,要看我们怎么使用。不能因为高射炮打蚊子不方便就说高射炮没用。

恰当的使用结构体指针,有利于我们写出更加紧凑,效率更高的 C 程序。一周有五天工作日,两天周末。一般来说,在工作日(weekday),人们的睡觉时间较短,工作时间较长,所以我们定义 weekday 函数来规划工作日的时间如下:

void weekday(struct week wd)
{
    wd.sleep_time = 7.0;        // 7 小时
    wd.work_time = 8.5;     // 8.5 小时
}

而在周末(weekend)则反过来,工作间较短,睡觉时间较长,所以我们定义 weekend 函数来规划周末的时间如下:

void weekend(struct week we)
{
    we.sleep_time = 9.0;        // 9 小时
    we.work_time = 2.5;     // 2.5 小时
}

这两个函数很好的规划了一周七天的睡觉和工作时间,但是却并不好用。为什么呢?因为它俩只在自己内部规划了,我们外界看不到啊!想在 main 函数把规划好的时间打印出来都办不到,因为它俩在自己内部规划好以后,就把“规划书”销毁了。

这里把 weekday 和 weekend 函数的局部变量比作“规划书”,函数退出后,局部变量就自动销毁了。可以参考《》一节。

可能你会说,那我可以把“规划书”返回给 main 函数啊,让 weekday 和 weekend 函数有返回值就可以了:

struct week weekday(struct week wd)
{
    wd.sleep_time = 7.0;        // 7 小时
    wd.work_time = 8.5;     // 8.5 小时
    return wd;
}
struct week weekend(struct week we)
{
    we.sleep_time = 9.0;        // 9 小时
    we.work_time = 2.5;     // 2.5 小时
    return we;
}
int main()
{
    struct week w;
    w = weekday(w);
    printf("weekday, sleep time: %0.1f, work time: %0.1f\n",
                w.sleep_time, w.work_time);
    weekend(w);
    printf("weekend, sleep time: %0.1f, work time: %0.1f\n",
                w.sleep_time, w.work_time);
    return 0;
}

是的,这的确是一个解决问题的办法,main 可以把 weekday 和 weekend 函数的“规划书”打印出来了。

但是这种解决问题的办法有一点臃肿,很多程序员把这样的代码称为“不优雅”的代码。你看,main 现在有一份空的“规划书”,需要 weekday 和 weekend 函数处理。weekday 和 weekend 函数能处理,但是它们要复制一份“规划书”回到自己内部做,这种复制就造成了空间浪费。此外,weekday 和 weekend 函数做完了规划书,还要把“规划书”再从自己内部取出,传给 main,这就有时间浪费

更节约资源,更有效率的做法是:weekday 和 weekend 函数处理这份“规划书”时,直接处理 main 里的空“规划书”就可以了。不要复制后再处理,完事了还要在从自己内部传出。那,weekday 和 weekend 函数应该怎么修改呢?请看:

void weekday(struct week *wd)
{
    wd->sleep_time = 7.0;       // 7 小时
    wd->work_time = 8.5;        // 8.5 小时
}
void weekend(struct week *we)
{
    we->sleep_time = 9.0;       // 9 小时
    we->work_time = 2.5;        // 2.5 小时
}
int main()
{
    struct week w;
    weekday(&w);
    printf("weekday, sleep time: %0.1f, work time: %0.1f\n",
                w.sleep_time, w.work_time);
    weekend(&w);
    printf("weekend, sleep time: %0.1f, work time: %0.1f\n",
                w.sleep_time, w.work_time);
    return 0;
}

看到了没,利用指针,整个 C 代码简洁多了。weekday 和 weekend 函数接收到的参数都是 main 里结构体变量 w 的地址,所以它俩都是直接操作 w 的。这样就不用在自己的栈帧里复制一份 w 再处理了,也不用在处理完毕还要 return 给 main 了。

看到这里,你可能会说,什么嘛,不就是用指针代替了结构体做参数吗?指针说不定比结构体还要耗空间呢!对吗?一起来看下:结构体变量 w,它占用内存至少两个 sizeof(double) 的空间(一个 double 型数据通常占用 8 字节空间)。而一个指针,不管它是什么类型的,在大多数 32 位计算机中,它只占 4 字节空间,在大多数 64 位计算机中,它也仅仅占 8 字节空间。所以使用指针做weekday 和 weekend 函数的参数,在空间上,绝对是比直接使用 week 结构体节约空间的,何况指针还提升了效率,简洁了代码。

如果只是一个 char 型变量,它只占用 1 字节空间,这时使用指针的确更浪费空间。但是如果是一个非常复杂的结构体,它占用的内存空间甚至几千字节,这时使用指针就非常节约空间了。所以说,工具是死的,人是活的。

到这里,相信你已经了解 C 语言指针在节约空间,提升程序效率方面的作用了。事实上,这里我们介绍的仅仅是指针的冰山一角,在以后的文章里,你会愈发觉得 C 语言指针的强大的。

阅读更多:   C语言
已有 2 条评论
  1. Max

    连续看了你写的多篇 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