Function Pointers

Function Pointers as arguments

  1. Examine the following code.
    int f1(int (*f)(int));
    int f2(int i);
    
    int main(void){
      printf("Answer: %d\n", f1(f2));
      return 0;
    }
    
    int f1(int (*f)(int)){
      int n = 0;
      while ((*f)(n)) n++;
      return n;
    }
    
    int f2(int i){
      return i * i - i - 12;
    }
    
    1. What do you predict the code will do?

    2. Verify your guess by running the code

  2. Consider a function with the following prototype:
    int sum(int (*f)(int), int start, int end);
    The call sum(g,i,j) should return g(i) + ... + g(j).
    1. Write the function sum.

    2. Write a function g1 which takes in an integer and returns the integer squared. Test sum on g1, using various values for start and end so that you're confident sum works as desired.

    3. Write a function g2 which takes in an integer and returns the integer minus 1. Test sum on g2, using various values for start and end until you're confidence that sum works as desired.

  3. Consider the problem of giving a string as an argument to a function, and depending on what the string contains, executing a particular command. We will break this problem into two parts: First we're going to write a suite of commands we might want to execute. Then we will write a function that will execute a given command.

    1. The following code declares an un-named structure, which contains a string and a function.
      struct{
        char *cmd_name;
        void (*cmd_pointer)(void);
      }
      
      Use this to declare an array of structs, for various functions that you will write in the next step. For example, we might declare the following array:
      struct{
        char *cmd_name;
        void (*cmd_pointer)(void);
      }print_cmds[] = 
        {{"smile", printSmiles},
         {"compliment", printCompliment},
         {"x", printxs}
        };
      

      The idea here is that each of printSmiles, printCompliment and printxs will be the name of a function with no parameters and with return type void (since those are the restrictions placed on the struct). Your array should have at least 5 items.

    2. Write the 5 (or more) functions from your previous step. Each function should have no parameters (void) and return type void. Other than that, it's up to you what the functions do.

    3. Write a function that, when given a string as its argument, searches your array of structures for a matching command name, then calls the function associated with that name.

      Use the following prototype:

      void execute_command(const char *cmd);

      A few hints to get you started on this one:

      • You may find the strcmp function handy, which is in the library string.h. See Section 23.6 of our textbook to review this function.
      • To loop through the array, you'll need to know the size in order to know when to stop iterating. However, the size is not given as a parameter in the prototype, so you'll need to compute the size of the array within the function. Review section 9.3 of our textbook if you've forgotten how to calculate the size of an array.
    4. Test out that your function from the previous step works by calling it with different parameters from main.