Difference between revisions of "ES101 - Lesson 8 : Functions with Pass-By-Reference"

From Embedded Systems Learning Academy
Jump to: navigation, search
(Basics of Pointers)
(Assignment)
Line 119: Line 119:
  
 
==Assignment==  
 
==Assignment==  
# Build the following functions and use meaningful names for each function.
+
# Declare and define the following functions:
#*<b>1a.</b>  A function asks to input an integer, scans it and returns the input data.
+
#*<b>1a.</b>  getInt()  : asks to input an integer, scans it and returns the input data.
#*<b>1b.</b>  A function asks to input a floating-point number, scans it and returns the input data.
+
#*<b>1b.</b>  getFloat() : asks to input a floating-point number, scans it and returns the input data.
#*<b>1c.</b>  A function that takes a char pointer to a char array, asks for the user‟s first name, and stores it into the array using the pointer.
+
#*<b>1c.</b>  getName(char* name) : takes a char pointer to a char array, asks for the user's first name, and stores it into the array using the pointer.
#*<b>1d.</b>  A function that takes two integer pointers and swaps the numbers.
+
#*<b>1d.</b>  swap(int* a, int* b): takes two integer pointers and swaps the numbers.
# Ask the user to input two integers using the function built in 1a, swap them using your swap function, and print the values on the screen.
+
# Finish the sample code (note the TODOs) and run the program :
# Declare an array of 5 floating point numbers, ask the user to input five floating point numbers by calling the function in 1b five times, and store the value to the five index locations of the floating-point array. Create a function that can calculate the average of floating-point array and returns the average. Using this function, get the average of the user input and print it out.
+
#* TODO 1: Call the swap function and print the swapped values
# Ask the user to input their name using the function built in 1c and print the name using a for loop in capital letters.
+
#* TODO 2 and TODO 3: Declare array of float and get input to the array using getFloat()
 +
#* TODO 4: Call getAverage() to get average, and output the average to the user.
 +
 
 +
<syntaxhighlight lang="c">
 +
int main(void)
 +
{
 +
    // Get the name from the user :
 +
    char name[32];
 +
    getName(name);
 +
 
 +
    int my_int_one = getInt();
 +
    int my_int_two = getInt();
 +
   
 +
    // TODO 1 : Call your swap() function to swap values of my_int_one, and my_int_two
 +
 
 +
    // TODO 2 : Declare array of 5 floating-point numbers
 +
 
 +
    // TODO 3 : Use for loop to get input and store to the array elements :
 +
    for(int i=0; i<5; i++) {
 +
        array[i] = getFloat();
 +
    }
 +
 
 +
    // TODO 4 : Call getAverage function to get the average
 +
    // then store this to a variable and print it out.
 +
    float average = getAverage( <fill in the code >);
 +
 
 +
    return 0;
 +
}
 +
</syntaxhighlight>
  
 
==Questions==
 
==Questions==

Revision as of 18:22, 17 October 2012

Objective

You will learn the basics of pointers, which are used in combination with the functions.

Pass-by-value type of functions pass just the value of the variables into a function, but with a simple change, you can use functions that accept pass-by-reference type of variables. This is a very powerful concept that will allow your functions to change the values of the parameters.

Basics of Pointers

So far, pass-by-value is what you've used when you designed your functions to take inputs as parameters. Pass-by-reference passes a variable's memory address instead of the variable's value; therefore, you can change the data at that memory address hence changing the input value. Let's start with the basics of a pointer:

void main()
{
    int my_int_one = 0;
    int my_int_two = 0;

    // A pointer is declared by using the *
    int* my_int_ptr;

    // Point the my_int_ptr to the memory address of my_int_one.  Note the & operator
    my_int_ptr = &my_int_one;

    // By using the *, we dereference the memory of my_int_ptr and write 1 to it:
    *my_int_ptr = 1;

    // Without using my_int_one, we modified it to be the value of 1
    printf("my_int_one = %i\n", my_int_one);

    // Let's modify my_int_two indirectly:
    my_int_ptr = &my_int_two;
    *my_int_ptr = 2;

    // This will print 2:
    printf("my_int_two = %i\n", my_int_two);
}

Let's summarize important points:

  • A pointer is declared by using the * right before the variable name
  • A pointer can point to different memory locations by setting it to & (address) of another variable
  • A pointer's pointed value can be changed by referencing it.


Pass By Reference

Pass by reference provides a mean to provide input to functions by specifying a memory location, which allows the function to modify caller's variables. In other words, instead of just merely giving a value, you pass the pointer of variable(s), and the pointer points to the memory address where the data is stored. The values are then accessed by using the * operator inside the function, which is called the dereference operator. Students often get confused with & and * symbols. & refers to the memory address whereas as * refers to a value stored at this memory address.

// Declare foobar() that takes pointers of int and float
void foobar(int *intInput, float *fpInput);

int main(void)
{
   // We can no longer do this since we have to provide
   // addresses of some variable
   foobar(1, 1.2);        // ERROR!
   foobar(anInt, aFloat); // ERROR!

   // Pass variable addresses to foobar()
   int anInt = 1;
   float aFloat = 2.3;
   foobar(&anInt, &aFloat);

   // After function call to foobar(): anInt and aFloat are zero
   printf("Variables now: %i, %f\n", anInt, aFloat);
}

void foobar(int *intInput, float *fpInput)
{
   // intInput and fpInput are addresses, so to read/write
   // the values at these addresses, we must use * (dereference)
   // operator
   printf("Input was: %i, %f\n", *intInput, *fpInput);

   // Modify the inputs:
   *intInput = 0;
   *fpInput  = 0;
}

Similar to how you provided address to scanf function, you must provide address of variables to foobar(), when calling the function otherwise a compiler error will be encountered as seen by first two calls to foobar() in the figure above. The third call to foobar() shows correct function call, which passes addresses of anInt and aFloat variables. The main() function called foobar() with values as 1 and 2.3, and, after foobar() returns, the values of the variables are set to 0 by foobar().

Passing Arrays to a Function

Passing arrays to a function is not much different than passing a pointer. This is because to pass an array to a function, you actually still pass the address of its first element. Arrays usually consist of large number of elements; therefore, passing array pass-by-value would be time consuming because each elements needs to copied. To address this issue, the address of first element of the array is passed to functions (pass-by-reference). See the examples below for illustration.

void getName(char *charArray);
float getAverageOfFloatingPointArray(float *floatArray, int elements);

int main(void)
{
   char userName[50];
   getName(userName);
   printf("Your name is: %s\n", userName);

   float samples[4] = {1.1, 2.2, 3.3, 4.4};
   float average = getAverageOfFloatingPointArray(samples, 4);
   printf("Average = %f\n", average);
}

void getName(char *charArray)
{
   printf("Enter your name: ");
   // No & symbol needed since the pointer is already the address
   scanf("%s", charArray);
}

float getAverageOfFloatingPointArray(float *floatArray, int elements)
{
   int i = 0;
   float sum = 0;
   for(i = 0; i < elements; i++)
   {
      sum += floatArray[i];
   }

   float average = sum / elements;
   return average;
}

Notice that when main() calls the getName() and getAverageOfFloatingPointArray() functions, it just passes the arrays without the & operator; this is because the array name itself is the address of the first element of the array. The one problem is that getAverageOfFloatingPointArray() will not know how big the array is, so another parameter, elements, is given, such that this function can know how many elements there are in the array. Again, this is similar to pass-by-reference, except how the arrays are passed. One last thing to note is that when the getName() function tried to do scanf, it did not need to pass the address of charArray, because the charArray is the address to begin with. Furthermore, notice that the floatArray was accessed simply by using index locations.

Assignment

  1. Declare and define the following functions:
    • 1a. getInt()  : asks to input an integer, scans it and returns the input data.
    • 1b. getFloat() : asks to input a floating-point number, scans it and returns the input data.
    • 1c. getName(char* name) : takes a char pointer to a char array, asks for the user's first name, and stores it into the array using the pointer.
    • 1d. swap(int* a, int* b): takes two integer pointers and swaps the numbers.
  2. Finish the sample code (note the TODOs) and run the program :
    • TODO 1: Call the swap function and print the swapped values
    • TODO 2 and TODO 3: Declare array of float and get input to the array using getFloat()
    • TODO 4: Call getAverage() to get average, and output the average to the user.
int main(void)
{
    // Get the name from the user :
    char name[32];
    getName(name);

    int my_int_one = getInt();
    int my_int_two = getInt();
    
    // TODO 1 : Call your swap() function to swap values of my_int_one, and my_int_two

    // TODO 2 : Declare array of 5 floating-point numbers

    // TODO 3 : Use for loop to get input and store to the array elements :
    for(int i=0; i<5; i++) {
        array[i] = getFloat();
    }

    // TODO 4 : Call getAverage function to get the average
    // then store this to a variable and print it out.
    float average = getAverage( <fill in the code >);

    return 0;
}

Questions

Answer the following questions to complete the lab.

  1. Although pass-by-reference can be used to substitute all pass-by-value functions, why is pass-by-value be considered safer?
  2. When passing an integer array to a function, why do you also need to pass the number of elements in that array?