When defining a new function, you need to first prepare an adequate specification. This will consist of answers, expressed in plain English, to the following questions:
C function names, like C variable names, consist of a sequence of characters, including upper and lower case alphabetics, the digits 0 through 9, and the underscore character _. The name should always begin with an alphabetic. Names can be as long as you wish, but anything much longer than 20 characters becomes unwieldy and error-prone and should usually be avoided. All function names must be unique within a given program. Most C programmers use only lower case alphabetics in function and variable names (i.e., no capitals). However, this is only a convention, and is not a compulsory part of the C language definition. Names of functions are usually chosen based on verbs because they do something - whereas names of variables tend to be based on nouns (they just "are"). It is important to think carefully about the names of both functions and variables in a C program. While the compiler really doesn't care (as long as the names are unique) these choices can make a big difference to how easy or difficult it is for another human being to understand how the program is intended to operate.
Many functions can behave differently based on certain information passed into them by their calling function. For example, the standard function put_string() is able to print out any string on the screen. Which particular string it will print out on any particular occasion is specified by the calling site - the invocation specifies a particular string to be passed into the function.
The specification of the information to be passed into a function will thus determine the layout of its argument list. The argument list states how many arguments the function will accept, what types they must be, and what names will be used within the body of the function to refer to these arguments.
Many functions generate a result of some sort, which must be made accessible to its calling site, after the function has finished execution.
In the special case of objects of string_type, this can be achieved by the calling site passing in a string variable to the function; any changes which the function makes to this string, will still be visible, after the function terminates, at the calling site. This is called passing by reference, and is the mechanism used, for example, by the get_string function.
However, this does not work for information of other types. Thus, for example, if a variable of integer_type is passed into a function, all that "really" happens is that a copy of this variable is made available to the function. Any changes which the function makes to that value are lost when the function exits. This is called passing by value. In this case, the idea of passing in a variable for a function to modify cannot be used to allow a function to pass information back to its calling site. In that case, you should use the return value mechanism. If you place a return statement in your function then, when that statement is executed, the function will immediately terminate, and the specified value will be made available at the calling site, in the position where the function was invoked. This is the mechanism used, for example, by the string_floating_point function. Typically, this return value is assigned to a variable at the calling site, so that it can be stored for use in subsequent statements.
The return mechanism cannot be used to pass back values of string_type. In that case, you must use the passing by reference mechanism, where a string variable, belonging to the calling site, is passed into the function as an argument, and modified by it.
The specification of the information to be passed back from a function may thus lead to the specification of additional arguments (passing by reference), or to the specification of a return type (or, possibly, both).
That is, having stated what, if any, information if passed in, and what, if any, information is passed back, you need to state, in plain English, what the effect of the function is supposed to be.
The idea of defining a new function usually arises in the context of some "higher level" function which you are already writing. Essentially, you want to defer coding some more detailed activity or calculation. This is called "top-down" design, and is a typical strategy for all forms of engineering design, not just software. So, for the time being, you just want to put in a call to a function, which, at some later stage, you will define in detail. The coding of this function call will, implicitly, at least, answer all of the questions we have just raised.
Having answered these questions, you should then enter the skeleton definition of the function:
<return type> <function name> ( <argument list> ) { <function body> }
You then go back and fill in the slots. For example, suppose we decide to define a function called foo, which will accept one argument of floating_point type, and generate no return value, we can immediately make out the following skeleton:
void foo(floating_point_type arg) { }
You need to minimally provide this skeleton, just to allow an invocation of the function to even be compiled properly. You may well temporarily put in a "dummy" body to the function - called a stub - just to allow you to test out the higher level invocation. But, eventually, you must come back and fill in the body of the function definition with the actual C statements which will make it, upon invocation, carry out the activities specified for it.