尽量使用功能好吗?

时间:2013-06-27 15:41:04

标签: c linux function

当我阅读开源代码(Linux C代码)时,我发现使用了很多函数而不是在main()上执行所有操作,例如:

int main(void ){
    function1();
    return 0;
}

void function() {
    // do something
    function2();
}

void function2(){
    function3();
    //do something
    function4();
}

void function3(){
    //do something
}
void function4(){
    //do something
}

你能告诉我尽可能多地使用函数的优点和缺点吗?

  • 易于添加/删除功能(或新操作)
  • 代码的可读性
  • 源效率(?),因为函数中的变量将被销毁(除非动态分配完成)
  • 嵌套函数会减慢代码流吗?

6 个答案:

答案 0 :(得分:11)

  • 易于添加/删除功能(或新操作)

当然 - 也很容易看出操作的上下文在哪里开始/结束。看到这种方式要比源中某些任意范围的线条容易得多。

  • 代码的可读性

你可以过头了。有些情况下,有一个功能或不拥有它不会对行数产生影响,但在可读性方面有所不同 - 并且它取决于一个人是否是正面的。

例如,如果你做了很多固定位操作,你会做出:

some_variable = some_variable | (1 << bit_position)
一个功能?会有帮助吗?

  • 由于函数中的变量被破坏而导致源效率(?)(除非动态分配完成)

如果源是合理的(例如,你没有重复使用变量名称超过它们的实际上下文),那么它应该无关紧要。编译器应该确切地知道值使用停止的位置以及可以忽略/销毁的位置。

  • 嵌套函数会减慢代码流吗?

在某些情况下,地址别名无法正确确定。但在大多数计划中,这在实践中并不重要。当它开始变得重要时,你可能会使用分析器浏览你的应用程序并发现有问题的热点。

编译器现在在内联功能方面相当不错。你可以信任他们至少做一个不错的工作,摆脱所有调用开销与功能长度本身相当的情况。 (以及许多其他情况)

答案 1 :(得分:4)

随着您编写的代码量的增加,这种使用函数的做法非常重要。这种分离功能的做法改善了代码卫生并使其更易于阅读。我在某处读到,如果它只能被您阅读(在某些情况下我认为没问题),那么确实没有代码点。如果您希望代码继续存在,那么它必须是可维护的,并且可维护性是通过尽可能简单地创建函数来创建的。还要想象你的代码库超过100k行的位置。这很常见,想象一下主要功能。这将是一个绝对的噩梦。将代码划分为函数有助于创建可分离性程度,因此许多开发人员可以在代码库的不同部分工作。所以基本上简短的答案是肯定的,必要时使用功能是很好的。

答案 2 :(得分:3)

函数应该可以帮助您构建代码。基本的想法是,当你在代码中找到一些可以用连贯,自包含的方式描述的地方时,你应该考虑把它放到一个函数中。

优点:

  • 代码重用。如果你做了很多次操作,为什么不写一次,多次使用?
  • 可读性:理解strlen(st)while (st[i++] != 0);
  • 更容易理解
  • 正确性:上一行中的代码实际上是错误的。如果它散落在周围,你甚至可能看不到这个bug,如果你将它固定在一个地方,那么这个bug就会留在别的地方。但是如果在一个名为strlen的函数中使用此代码,您将知道它应该做什么,并且您可以修复它一次。
  • 效率:有时,在某些情况下,编译器在编译函数内部时可能会做得更好。不过,你可能不会事先知道它。

缺点:

  • 将代码拆分成函数只是因为它是一件好事并不是一个好主意。如果你发现很难给这个功能一个好名字(用你的母语,不仅仅是在C语言中)它是可疑的。 doThisAndThat()可能是两个函数,而不是一个函数。 part1()完全错了。
  • 函数调用可能会花费您执行时间和堆栈内存。这并不像听起来那么严重,大多数时候你应该关心它,但它就在那里。
  • 当被滥用时,可能会导致许多功能部分工作并将其他部分从此处委派给那里。太多的论点也可能妨碍可读性。

基本上有两种类型的函数:执行一系列操作的函数(在某些上下文中称为“过程”),以及执行某种形式计算的函数。这两种类型通常混合在一个函数中,但它有助于记住这种区别。

各种函数之间还有另一个区别:保持状态的那些(如strtok),可能有副作用的那些(如printf)和那些“纯”的函数(如{ {1}})。像sin这样的函数本质上是一种特殊的不同构造,在面向对象编程中称为Object。

答案 3 :(得分:1)

您应该使用每个执行一个逻辑任务的函数,在抽象级别上使每个函数的函数易于逻辑验证。例如:

void create_ui() {
    create_window();
    show_window();
}

void create_window() {
    create_border();
    create_menu_bar();
    create_body();
}

void create_menu_bar() {
    for(int i = 0; i < N_MENUS; i++) {
        create_menu(menus[i]);
    }
    assemble_menus();
}

void create_menu(arg) {
    ...
}

现在,就创建UI而言,这不是人们想要的方式(你可能想要传入并返回各种组件),但逻辑结构正是我想要的注重。将您的任务分解为几个子任务,并使每个子任务成为自己的功能。

不要试图避免优化功能。如果这样做是合理的,编译器会为你内联它们;如果没有,开销仍然很小。从这里获得的可读性的提升比将所有内容放在单片功能中所获得的速度更重要。

关于你的标题问题,“尽可能”,没有。在合理范围内,足以让我们看到每个函数在一个舒适的抽象层次上所做的事情,不会少,也不会更多。

答案 4 :(得分:0)

您可以使用的一个条件:如果部分代码将被重用/重写,则将其放入函数中。

答案 5 :(得分:0)

我想我认为像legos这样的功能。你有数以百计的小件可以放在一起。由于所有这些设计精良的通用小件,你可以做任何事情。如果你有一个看起来像整个房子的乐高,你就不能用它来建造一架飞机或火车。同样,一段巨大的代码也没那么有用。

功能是您在设计项目时使用的砖块。精心选择的功能分离为小型,易于测试,自包含的“功能”,使您可以轻松构建和管理整个项目。他们的好处在于你可能认为存在的任何可能的效率问题。

老实说,任何大型项目的编码技巧都在于如何将其分解为更小的部分,因此功能是关键。