Fundamental C - Functions
Written by Harry Fairhead   
Monday, 19 March 2018
Article Index
Fundamental C - Functions
Void, Pass-by-Value

void

What if a function doesn't return a value?

This is allowed. Sometimes a function just does something and doesn't need to return a value. For example. the hello program, our first example of a function simply prints a value and returns with out a return value. You can include a return statement anywhere within a function to bring it to an end with or without a return value.

For example:

hello(){
    printf("Hello Function World");
    return;
}

It is good practice to always include a return statement within a function.

One final complication. How do you indicate the type of a function that doesn't return a value?

The answer is to use the type void. This makes C programs look mysterious but all it means is something like "nothing" or "not applicable" or ...

So the hello program really should be written:

void hello(){
    printf("Hello Function World");
    return;
}

You will discover that C tends to use the term "void" when anything isn't of a fixed or known type.

The main Function

If you look again at any C program you will now recognize the main program as actually being the main function. The main function is just a standard function that is automatically called when your program is loaded. It then proceeds to get the work done by calling other functions.

int main(int argc, char** argv) { 
    lines of code that call other functions
    return (EXIT_SUCCESS);
}

The only thing that might puzzle you at this stage are the strange looking parameters. To understand these in detail we will have to find out about pointers in a later chapter.

Declaring Functions

So far we have followed the rule that a function is declared before we attempt to use it. This results in all the functions used in a program being listed first and then the code that uses them. To many programmers this is the wrong way round. They want to read the main program first and find out what it does and then read the functions that it uses and then the functions that they use and so on.

You can place a functions code anywhere within the file, or even in another file as long as you include a short declaration - a prototype - for the function before it is used. A prototype simply specifies what the types are that are used in the function declaration.

For example the add function's prototype is:

int add(int,int);

which declares a that the add function takes two int parameters and returns an int. You can include parameter names if you want to but it general practice to strip the prototype down to just the types.

As long as the prototype is included in the file before the first use of the function everything will work. The full declaration of the function can be later in the file or in another file altogether. The prototype provides enough information for the compiler to check that you are using the function correctly.

The Expression Principle - Pass-by-Value

There is a general principle in C that anywhere you can use a number you can use an expression that evaluates to the same type of value.

Until now we have been setting parameters to values but in fact you can pass a function an expression and this will be evaluated before the function is executed.

For example:

hello(3*2);

in this case the multiplication is performed and 6 is passed to the function.

Of course an expression can involve variables.

For example:

hello(3*count);

in this case the value in count is multiplied by 3 and the result passed to the function.

The limiting case of an expression is just a variable:

hello(count);

In this case the value in count is passed into the function.

This is usually called pass-by-value and it is one of the possible ways of passing data into functions. It is one of the simplest and you should now be able to understand what happens in the following example:

void test(int a){
   a=1;
}

var a=0;
test(a);

The question is what does a store after the function call? Is it 1 which is what it was assigned in the function or is it its original value of 0?

The answer is that it still holds 0. There is no connection between variables outside of the function and the parameters inside the function even if they have the same names. Because of the use of pass-by-value what happens is that the the value of a is passed to the function's parameter which also happens to be called a. When you assign to a in the function it is to a completely different variable than the a outside of the function.

This gives rise to the rule that

modifying variables inside a function has no effect on variables outside of the function.

This is good because it makes function isolated little chunks of code that are easy to understand and check.

There are parameter passing methods that do allow functions to change things outside of their own code and these are more dangerous even if they are sometimes useful. C only uses pass-by-value and we will have to see how to achieve other ways of passing parameters later.

Local Variables

This idea of functions as being isolated chunks of code goes beyond just the parameters. You can declare variables within a function and these are generally called local variables.

For example, in the add function we declared a local variable c:

int add(int a, int b) {
    int c = a + b;
    return c;
}

Just like the parameters this c has nothing to do with any variables called c outside of the function. The local variable c is created when the function starts executing and it is destroyed when the function returns. That is local variables only exist while the function is running - they have the same lifetime as the function. 

This should seem very reasonable to you but if you forget it you will try to write something like:

int counter(){
    int c=0;
    c=c+1;
    return c;
}

and in the main program:
printf("%d \n", counter());
printf("%d \n", counter());

The idea here is that c is incremented by 1 each time the function is executed but of course this doesn't work. The variable c is destroyed each time the function returns and so it doesn't matter how many times you call counter() c is created anew and set to 0 and then has one added to it. The function always returns 1.

Global Variables

If there are local variables are there global variables?

The answer is yes. In C global variables are often called "file level" variables because they are declared outside of any function.

A global variable will automatically be zeroed to a value that is appropriate for its type but it is usually better to initialize it. The most important thing about global variable is that they are created when the program starts and remain in existence until the program ends. They can also be accessed from within any function. The only exception to this is if the function declares a variable of the same name when the local variable is used - it overrides the global variable.

As a global variable exists for the lifetime of the program you can use to keep track of things throughout the execution of the program so now the counter function can be made to work:

int c=0;
int counter(){ 
    c=c+1;
    return c;
}

now if you put

printf("%d \n", counter());
printf("%d \n", counter());

in the main program you will see 1 followed by 2 and the variable c is being used to count the number of times the function has been used.

When you first start to construct larger programs there is a tendency to create lots of global variables because this means you don't have to pass them as parameters to functions. The functions can just make use of global variables as if they were their own. The problem is that global variables are not the property of any function and they have to be hard coded into the functions. Using lots of global variables produces a program that is fragile in the sense that any small change can have effects further away from where the change occurred.

Using functions and local variables makes program up out of small isolated units that can be understood and debugged in isolation.

Summary

  • a function is a block of code that can be executed by using its name.
  • a function can have a set of parameters and a return value.
  • you have to specify the data type of each parameter and the return value
  • if there is no return value then use void to indicate its type

functiontype functionname(
       parametertype parametername, ...){
       lines of code
    return value
};

  • the main function is simply a function that the system starts running when your program is loaded.
  • functions have to be defined before they are first used unless you include a prototype which gives the return type and parameter types before the first use.
  • parameters are passed by value to the function and any changes to the parameters do not effect any variables in the calling program. This makes functions isolated chunks of code.
  • variables declared inside function are local variables and they only exist while the function is executing and they have nothing to do with any variables of the same name anywhere else in the program. This makes functions isolated chunks of code.
  • global variables are declared outside of any function and they live for the entire life of the program and they can be accessed by any function without needing to be passed as parameters.
  • If a function defines a local variable of the same name then this takes precedence - it overrides the global variable of the same name.

 

Fundamental C: Getting Closer To The Machine

Now available as a paperback and ebook from Amazon.

  1. About C
      Extract Dependent v Independent
                  & Undefined Behavio
  2. Getting Started With C Using NetBeans
  3. Control Structures and Data
  4. Variables
      Extract Variables
  5. Arithmetic  and Representation
      Extract Arithmetic and Representation
  6. Operators and Expression
      Extract: Expressions
      Extract Side Effects, Sequence Points And Lazy Evaluation
      First Draft of Chapter: Low Down Data
  7. Functions Scope and Lifetime
  8. Arrays
      Extract  Simple Arrays
      Extract  Ennumerations
  9. Strings
      Extract  Simple Strings
     
    Extract: String I/O ***NEW!!
  10. Pointers
      Extract  Starting Pointers
      Extract  Pointers, Cast & Type Punning
  11. Structs
      Extract Basic Structs
      Extract Typedef
  12. Bit Manipulation
      Extract Basic Bits
      Extract Shifts And Rotates 
  13. Files
     Extract Files
     
    Extract Random Access Files 
  14. Compiling C – Preprocessor, Compiler, Linker
     Extract Compilation & Preprocessor

Also see the companion volume: Applying C

<ASIN:1871962609>

<ASIN:1871962463>

<ASIN:1871962617>

<ASIN:1871962455>

 

Related Articles

Remote C/C++ Development With NetBeans

Raspberry Pi And The IoT In C

Getting Started With C/C++ On The Micro:bit

To be informed about new articles on I Programmer, sign up for our weekly newsletter, subscribe to the RSS feed and follow us on Twitter, Facebook or Linkedin.

Banner


Rust And C++ Should Be Friends?
20/11/2024

The Rust Foundation has just released a statement on Rust and C++ interoperability and Google is ponying up $1 to see that it gets done.



Zitadel Announces Funding And Future Plans
21/11/2024

Zitadel has announced a major funding round that will be used to expand technical teams and fund further product development. The company is the creator of an open source project for cloud-native iden [ ... ]


More News

espbook

 

Comments




or email your comment to: comments@i-programmer.info



Last Updated ( Tuesday, 11 September 2018 )