Skip to content
Physics and Astronomy
Home Our Teaching Resources C programming functions.html
Back to top

Scientific programming in C: functions organise our code

This should be mainly revsion.

Seven plus or minus two?

In the 1950s George Miller realised that people could typically remember about 7 (±2) things in their short term memory. Interestingly, he also pointed out that seven seems to be a typical limit in other slightly different memory-based contexts. In practice this means that anything we can't express in around seven independent concepts is going to be very difficult to deal with.

Miller also pointed out that we are able to mentally organise more complicated sets of thoughts or things by organising them into groups: with a little practice most of us can remember and think about seven groups each of seven things even though we can't handle all forty-nine together at one time.

Whilst it's easy to over-simplify this, the basic idea is valid: we can't handle complicated things and we have to organise them into independent chunks. In this context, "independent" means that when we are thinking about one chunk, or function, we don't have to think about the other functions.

The square law

An early study by IBM showed that the time taken to get a program working was proportional to the square of its size. This make sense if we think of the major task as being debugging: if the program is twice the size there will be twice as many mistakes and each mistake will take twice as long to find.

Functions can help here by allowing us to debug one indepedent chunk at a time.

Aside: Complexity is increasing not decreasing

  • Almost every commercial project is written by a team of people, not just one person.

  • People leave these teams.

  • Software projects are often written by teams of people who have never even met each other.

  • Much more time is spent maintaining (adding new features or fixing old bugs) programs than writing brand-new ones.

  • Modern programs have to be internet aware: they have to interact with other programs written by people we've never met running on other computers running other operating systems.

Historically, the first response to this was to split code into self-contained units called functions.

Functions

Functions break large computing tasks into smaller ones, and enable people to build on what others have done instead of starting over from scratch.
Kernighan & Ritchie.

Functions should be short and sweet, and do just one thing... and do that well.
Torvalds

The purpose of a function is to make life easier for the person who is calling it.

  1. A function allows the caller to think in terms of what the function does rather than how it does it.

  2. A function allows debugging to procede one task at a time, thus linearising the debugging process.

Structuring functions

Imagine our task can be split into three sensible functions each of which can be split into two or three subfunctions for a total of eight subfunctions.. There are two ways to do this:

Bad structure

  • function_1
  • function_2
  • function_3
  • function_4
  • function_5
  • function_6
  • function_7
  • function_8

Proper structure

  • function_a
    • function_a_part_1
    • function_a_part_2
    • function_a_part_3
  • function_b
    • function_b_part_1
    • function_b_part_2
  • function_c
    • function_c_part_1
    • function_c_part_2
    • function_c_part_3
  • Turn to your neighbour and discuss why this might be.

Code that's used more than once

A related use of functions is that some tasks are required from many parts of the program. The most obvious examples are the standard library functions such as printf(), sin(), etc. We also will write code that will be used several times and that also should be a function.

Avoid copy and paste!

Sadly, when marking student work one often sees large amount of repeated code. It's quite clear what's happened: write a section of code; copy-paste, change all the "1"s to "2"s.

Don't use copy-and-paste, use cut-and-paste to make it into a function.

Problems with functions

Trivial functions

We have already stated that functions should be non-trivial. As an example of a trivial function consider the following:
    /*
     * Add two numbers together
     */
    float add_two_floats(float num1, float num2) {
      float sum;
    
      sum = num1 + num2;
      return sum;
    }

This is bad because it is simpler and clearer to just write:

  z = x + y;
rather than:
  z = add_two_floats(x, y);

Functions that do two things

calculate_area_of_a_square_and_check_the_spelling_of_some_text_
and_make_me_a_cup_of_coffee( black, ! sugar );

Side effects

A side effect is where a function that is advertised as doing one thing also does something else ("I know I'll always want to do it so I might as well do it here").

Hidden assumptions

This is the converse of a side effect: we implicitly assume that something else has already been done without actually saying so. If this is totally unavoidable then we should :
  • document it in the comment at the top of the function

  • check inside the function to see if it has been done and if not warn the user (and probably quit the program.)

Interface errors

The problems in the section above are essentially beginners errors. Interface errors are the big one.

An interface error is where we are making a slightly different assumption inside a function that in the function we are calling it from.

  • We may disagree on what exactly the function does.

  • We may disagree on what exactly the arguments are.

  • We may disagree on some other assumption.

Examples of interface errors

  • In a kinetics problem we have a variable called energy: in one part of the program we assume it is the kinetic energy, in another the total (kinetic plus gravitational potential) energy.

  • In the same problem, h is the height (upwards) but the acceleration a is taken to be downwards because g is positive.

  • We call a function which has as an argument a heat capacity c, we assume it wants capacity at constant volume, it wants constant pressure.

  • In 1999 NASA lost the Mars Orbiter satellite because they were using metric units and a contractor imperial (feet and inches, etc.)!

Tests for interface errors

  • Is the name of the function clear?

  • Does the comment at the top of the function tell us everything we need to know without having to look at the body of the function?

Summary

A function should :
  1. do one thing and do that well.
  2. be clearly defined and easy to understand.
  3. let we think of the task at a higher level, in terms of what we are doing ("read in a positive integer") and not how we are doing it.
  4. either:
    1. enable the code to be simpler and shorter by being called from several places (avoid copy and paste!) or
    2. enable a piece of code that would otherwise violate Miller's limits to be understood within those limits.

Summary

The text of each key point is a link to the place in the web page.

                                                                                                                                                                                                                                                                       

Validate   Link-check © Copyright & disclaimer Privacy & cookies Share
Back to top