Functions are just code at an address

Real-World Analogy

Think of a TV remote's buttons. Each button stores a reference to some action — "change channel", "mute", "increase volume". The remote doesn't know what TV it's pointing at until you aim it. A function pointer is exactly that: a variable that holds the address of a function, and can be pointed at different functions at runtime. Whoever holds the pointer decides which function to call.

In C, functions live at memory addresses just like variables. A function pointer stores one of those addresses. Once you have the pointer, you can call the function through it — without knowing at compile time which specific function will be invoked.

Python/Java comparison: In Python you can pass functions around naturally — sorted(list, key=my_func) — because Python functions are first-class objects. In Java you use interfaces or lambda expressions to achieve the same effect. In C, function pointers are the mechanism: lower-level, but the same idea. When you pass a function pointer to another function, you're doing what Python calls a "callback".

Why does this matter? Function pointers let you write generic algorithms. The standard library's qsort can sort any array of any type because you supply the comparison logic as a function pointer. State machines, event handlers, plugin systems, and virtual dispatch (the backbone of C++ vtables) all rely on function pointers.

The decay rule: Just like an array name decays to a pointer to its first element, a function name decays to a pointer to that function. So fp = add; and fp = &add; are equivalent. You will see both in real code.

Python (first-class functions)
# Functions are objects in Python
def add(a, b): return a + b
def mul(a, b): return a * b

# Assign function to variable
op = add
print(op(3, 4))   # 7

# Pass function as argument
def apply(fn, x, y):
    return fn(x, y)

print(apply(mul, 3, 4))  # 12

# Sort with key function
nums = [3, 1, 4, 1, 5]
nums.sort(key=lambda x: -x)
C (function pointers)
int add(int a, int b) { return a+b; }
int mul(int a, int b) { return a*b; }

/* Declare a function pointer */
int (*op)(int, int);

/* Assign (both forms work) */
op = add;   /* or: op = &add; */
printf("%d\n", op(3, 4));   /* 7 */

/* Pass as argument */
int apply(int (*fn)(int,int), int x, int y){
    return fn(x, y);
}
printf("%d\n", apply(mul, 3, 4)); /* 12 */

/* qsort — supply comparison fn */
qsort(arr, n, sizeof(int), cmp);
The declaration syntax is tricky

int *fp(int, int) is a function that returns int*. int (*fp)(int, int) is a pointer to a function taking two ints and returning int. The parentheses around *fp are mandatory. This is one of C's most notorious syntax quirks — use typedef to make it readable.

Key mental model

A function pointer is a variable that holds an address. That address points to executable code. Calling through the pointer is identical to calling the function directly — the CPU just jumps to that address. typedef creates an alias for the messy pointer type so your code stays readable.

Declaration, assignment, calling, and typedef

/* Declaration — "fp is a pointer to a function taking 2 ints, returning int" */
int (*fp)(int, int);
 ^    ^  ^    ^   ^
 |    |  |    |   └── parameter types
 |    |  |    └────── pointer indicator (MUST be in parentheses)
 |    |  └─────────── variable name
 |    └────────────── outer parens make * bind to name, not return type
 └─────────────────── return type

/* Assignment — both forms are valid */
fp = add;      // function name decays to pointer
fp = &add;     // explicit address-of — same result

/* Calling — both forms are valid */
int r1 = fp(3, 4);          // implicit dereference
int r2 = (*fp)(3, 4);        // explicit dereference

/* typedef — create a named type for the pointer */
typedef int (*compare_fn)(int, int);
compare_fn fp2 = add;    // much cleaner!
// From COMP2017 lecture: typedef int (*quack_f)(int);
Pattern: typedef <return> (*<TypeName>)(<params>); — then use TypeName like any type. This is the standard idiom in production C code and the COMP2017 exams.

Passing function pointers to other functions (callbacks)

/* Function that takes a function pointer as parameter */
int apply_twice(int (*fn)(int), int x) {
    return fn(fn(x));    // call fn twice
}

/* qsort from <stdlib.h> — prototype */
void qsort(void *base, size_t nmemb, size_t size,
           int (*compar)(const void *, const void *));
// compar must return: negative if a<b, 0 if equal, positive if a>b

/* Array of function pointers — dispatch table */
int (*ops[4])(int,int) = {add, sub, mul, divide};
ops[2](3, 4);   // calls mul(3, 4) → 12
Dispatch table: An array of function pointers where an index (often from user input or a state) selects which function runs. This is the pattern behind switch statements, interpreters, and C++ virtual functions.

Reading Complex C Declarations — The Precedence Rule

() and [] have higher precedence than *. When reading a declaration: start at the identifier, go right first (consuming () and []), then go left (consuming * and type qualifiers), then wrap outward past any enclosing parentheses and repeat.

Symbol Meaning Precedence
() function taking... HIGH (right first)
[] array of... HIGH (right first)
* pointer to... LOW (left after)
/* 1 — simple pointer */
int *p;
// → p is a [pointer to] [int]

/* 2 — array of pointers ([] binds before *) */
int *arr[5];
// → arr is an [array of 5] [pointers to] [int]
// ([] binds before * — NOT a pointer-to-array, IS an array-of-pointers)

/* 3 — pointer to array (parens override: * binds first) */
int (*arr)[5];
// → arr is a [pointer to] [array of 5] [int]
// (parens override: * binds first — IS a pointer-to-array)

/* 4 — pointer to function returning pointer to int */
int *(*fp)(int);
// → fp is a [pointer to] [function taking (int)] [returning pointer to int]

/* 5 — pointer to function returning int (the common case) */
int (*fp)(int, int);
// → fp is a [pointer to] [function taking (int, int)] [returning int]

/* 6 — the POSIX signal() signature — read with the rule */
void (*signal(int, void (*)(int)))(int);
// → signal is a [function taking (int, void(*)(int))]
//             [returning pointer to function taking (int) returning void]
// (the actual POSIX signal() signature — complex but readable with the rule)
Writing tip: Build declarations from the inside out. "Pointer to function returning int" → int (*fp)(...). "Array of 5 pointers to int" → int *arr[5]. Knowing which direction to read (right before left, parens override) makes even intimidating declarations straightforward.
Quick Self-Test

What does int *arr[5] declare?  (A) pointer to array of 5 ints   (B) array of 5 pointers to int   (C) function returning pointer to int
Answer: (B)[] binds before *, so arr is an array first; each element is then a pointer to int.

Complete programs you can compile and run

Example 1 — Basic function pointer: assign, call, pass as argument Week 5 Lecture
#include <stdio.h>

int add(int a, int b) { return a + b; }
int mul(int a, int b) { return a * b; }

/* Function that accepts a function pointer as a parameter */
int apply(int (*fn)(int, int), int x, int y) {
    return fn(x, y);   /* call through the pointer */
}

int main(void) {
    /* Declare a function pointer variable */
    int (*op)(int, int);

    op = add;                          /* assign — function name decays */
    printf("add: %d\n", op(3, 4));     /* call: 7 */

    op = mul;
    printf("mul: %d\n", op(3, 4));     /* call: 12 */

    /* Pass function pointer to another function */
    printf("apply(add,5,6): %d\n", apply(add, 5, 6));  /* 11 */
    printf("apply(mul,5,6): %d\n", apply(mul, 5, 6));  /* 30 */

    return 0;
}
Output
add: 7
mul: 12
apply(add,5,6): 11
apply(mul,5,6): 30
Example 2 — qsort with a comparison callback Week 5 Lecture — stdlib.h
#include <stdio.h>
#include <stdlib.h>

/* Comparison function: must match qsort's expected signature */
/* Returns negative/0/positive for less-than/equal/greater-than */
int cmp_int(const void *a, const void *b) {
    int x = *(const int *)a;
    int y = *(const int *)b;
    return x - y;   /* ascending order */
}

int cmp_int_desc(const void *a, const void *b) {
    return *(const int *)b - *(const int *)a;  /* descending */
}

int main(void) {
    int arr[] = {5, 2, 8, 1, 9, 3};
    int n = 6;

    /* qsort(array, count, element_size, compare_fn) */
    qsort(arr, n, sizeof(int), cmp_int);

    printf("Ascending:  ");
    for (int i = 0; i < n; i++) printf("%d ", arr[i]);
    printf("\n");

    qsort(arr, n, sizeof(int), cmp_int_desc);

    printf("Descending: ");
    for (int i = 0; i < n; i++) printf("%d ", arr[i]);
    printf("\n");

    return 0;
}
Output
Ascending: 1 2 3 5 8 9
Descending: 9 8 5 3 2 1
Example 3 — Function pointer array (dispatch table) Week 5 Lecture — vtable pattern
#include <stdio.h>

int add(int a, int b) { return a + b; }
int sub(int a, int b) { return a - b; }
int mul(int a, int b) { return a * b; }

/* typedef makes the array declaration readable */
typedef int (*bin_op)(int, int);

int main(void) {
    /* Array of 3 function pointers */
    bin_op ops[3] = { add, sub, mul };
    const char *names[] = { "add", "sub", "mul" };

    int a = 10, b = 3;
    for (int i = 0; i < 3; i++) {
        printf("%s(%d, %d) = %d\n", names[i], a, b, ops[i](a, b));
    }

    /* Select operation at runtime (e.g. from user input) */
    int choice = 1;   /* could come from scanf */
    printf("Choice %d: %d\n", choice, ops[choice](a, b));

    return 0;
}
Output
add(10, 3) = 13
sub(10, 3) = 7
mul(10, 3) = 30
Choice 1: 7
Example 4 — typedef for quack_f (2024 exam duck simulation) COMP2017 Exam Pattern
#include <stdio.h>

/* From lecture: typedef int (*quack_f)(int); */
typedef int (*quack_f)(int);

int loud_quack(int n) {
    for (int i = 0; i < n; i++) printf("QUACK! ");
    printf("\n");
    return n;
}

int soft_quack(int n) {
    for (int i = 0; i < n; i++) printf("quack ");
    printf("\n");
    return n;
}

/* A "duck" struct uses a function pointer for behaviour */
typedef struct {
    const char *name;
    quack_f quack;   /* behaviour injected via function pointer */
} Duck;

int main(void) {
    Duck d1 = { "Mallard", loud_quack };
    Duck d2 = { "Rubber",  soft_quack };

    printf("%s: ", d1.name); d1.quack(3);
    printf("%s: ", d2.name); d2.quack(2);

    return 0;
}
Output
Mallard: QUACK! QUACK! QUACK!
Rubber: quack quack
Example 5 — 2024 Final Exam Q6: Duck Simulation (complete walkthrough) 2024 Final Exam Q6 — 50 marks
Exam Context

This question tests: struct field access with ->, function pointers inside structs, pointer manipulation, malloc, fabs from math.h, and the difference between struct duck's value fields vs pointer fields. It was worth 50 marks on the 2024 Final Exam — study every part carefully.

The given struct (provided on the exam — you must understand every field):

#include <stdlib.h>
#include <math.h>

struct duck {
    float position[1];          /* duck's current x-position (array of 1 float) */
    float velocity[1];          /* current velocity: positive=right, negative=left */
    struct duck *duck_in_front; /* next duck in the queue (NULL if none ahead) */
    int (*quack)(int);          /* function pointer: takes int, returns int */
    int alive;                  /* 1 = alive, 0 = dead */
};

Part 0 (5 marks) — Reading the declaration. What type is quack in the struct?
Answer: int (*quack)(int) — a pointer to a function that takes one int parameter and returns int. The (*quack) syntax is mandatory: without the parentheses, int *quack(int) would declare a function, not a pointer.

Part 1 (10 marks) — same_direction(). Returns 1 if both ducks move in the same direction (or either has velocity 0), 0 otherwise.

int same_direction(struct duck *a, struct duck *b) {
    /* velocity[0] because position and velocity are arrays of 1 element */
    if (a->velocity[0] == 0.0f || b->velocity[0] == 0.0f) return 1;
    /* same sign = same direction */
    return (a->velocity[0] > 0 && b->velocity[0] > 0) ||
           (a->velocity[0] < 0 && b->velocity[0] < 0);
}

Part 2-5 (40 marks) — update_position(). Built up in layers across parts 2-5. The full combined solution handles all four cases: basic movement, dead duck in front, too-close collision, and overtaking.

void update_position(struct duck *d) {
    /* Part 2: add velocity to position */
    d->position[0] += d->velocity[0];

    /* Part 2: if no duck in front, we are done */
    if (d->duck_in_front == NULL) return;

    /* Part 5: if duck_in_front is dead, replace it with a new dead duck */
    if (!d->duck_in_front->alive) {
        struct duck *dead = malloc(sizeof(struct duck));
        dead->alive = 0;
        dead->duck_in_front = NULL;
        d->duck_in_front = dead;
        return;  /* done after replacing */
    }

    /* Part 3: signed distance (front minus self) */
    float dist = d->duck_in_front->position[0] - d->position[0];
    if (fabs(dist) < 1.0f) {
        /* too close — stop */
        d->velocity[0] = 0.0f;
        return;
    }

    /* Part 4: if d has overtaken duck_in_front, swap the queue order */
    if (d->position[0] > d->duck_in_front->position[0]) {
        struct duck *tmp = d->duck_in_front;
        d->duck_in_front = NULL;   /* d is now at the front */
        tmp->duck_in_front = d;    /* the overtaken duck is now behind d */
        d->quack(1);               /* announce the overtake via function pointer */
    }
}
Key concepts tested
position[0] / velocity[0] — fields are arrays of 1, so you index with [0], not just the field name
d->quack(1) — calling a function pointer stored inside a struct via the arrow operator
fabs(dist) — absolute value for floats, requires #include <math.h> and link with -lm
malloc(sizeof(struct duck)) — allocating a new struct on the heap for the dead duck replacement
Pointer swap — tmp holds the old front, then both duck_in_front pointers are rewired

Practice problems with solutions

P1 — Write a qsort callback to sort strings by length Week 5 Lecture

Write a comparison function that can be passed to qsort to sort an array of strings (char*) by their length (shortest first). The signature must be int cmp(const void *, const void *).

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int cmp_by_length(const void *a, const void *b) {
    /* a and b are pointers to elements of the array.
       The array holds char*, so each element IS a char*.
       a is a pointer TO a char*, i.e. char** */
    const char *sa = *(const char **)a;
    const char *sb = *(const char **)b;
    return (int)strlen(sa) - (int)strlen(sb);
}

int main(void) {
    const char *words[] = {"banana", "fig", "apple", "kiwi", "plum"};
    int n = 5;
    qsort(words, n, sizeof(char *), cmp_by_length);
    for (int i = 0; i < n; i++) printf("%s\n", words[i]);
    return 0;
}
Key cast: qsort passes const void * pointers to the array's elements. Since the array contains char *, each element is a char * value, and qsort gives us a pointer to that — so cast to const char ** then dereference. This double-pointer confusion is the most common qsort mistake.
P2 — Predict the output: function pointer call chain Week 5 Lecture

Without running the code, predict what is printed.

#include <stdio.h>
typedef int (*fn_t)(int);

int double_it(int x) { return x * 2; }
int add_ten(int x)   { return x + 10; }

int compose(fn_t f, fn_t g, int x) {
    return f(g(x));
}

int main(void) {
    fn_t fns[2] = { double_it, add_ten };
    printf("%d\n", fns[0](5));
    printf("%d\n", fns[1](5));
    printf("%d\n", compose(double_it, add_ten, 3));
    printf("%d\n", compose(add_ten, double_it, 3));
    return 0;
}
10
15
26
16
Line by line: fns[0](5) = double_it(5) = 10. fns[1](5) = add_ten(5) = 15. compose(double_it, add_ten, 3): first g(x) = add_ten(3) = 13, then f(13) = double_it(13) = 26. compose(add_ten, double_it, 3): first double_it(3) = 6, then add_ten(6) = 16.
P3 — Implement a generic "map" function using function pointers Week 5 Tutorial

Write a function map_array that takes an integer array, its length, and a function pointer. It should apply the function to every element in place. Use it to double all elements, then to negate all elements.

#include <stdio.h>

int double_it(int x) { return x * 2; }
int negate(int x)    { return -x; }

void map_array(int *arr, int len, int (*fn)(int)) {
    for (int i = 0; i < len; i++) {
        arr[i] = fn(arr[i]);
    }
}

int main(void) {
    int arr[] = {1, 2, 3, 4, 5};
    int n = 5;

    map_array(arr, n, double_it);
    for (int i = 0; i < n; i++) printf("%d ", arr[i]);
    printf("\n");  /* 2 4 6 8 10 */

    map_array(arr, n, negate);
    for (int i = 0; i < n; i++) printf("%d ", arr[i]);
    printf("\n");  /* -2 -4 -6 -8 -10 */
    return 0;
}
Pattern: This is the C equivalent of Python's map() — a higher-order function. The caller decides the transformation; the function provides the loop. This separation of concerns is the core value of function pointers.
P4 — Fix the bug: incorrect function pointer declaration Week 5 Lecture

The code below will not compile or will behave incorrectly. Find and fix the error in the function pointer declaration.

#include <stdio.h>
int greet(int n) { return n * 42; }

int main(void) {
    int *fp(int);   /* intended: pointer to function returning int */
    fp = greet;
    printf("%d\n", fp(2));
    return 0;
}
#include <stdio.h>
int greet(int n) { return n * 42; }

int main(void) {
    int (*fp)(int);   /* FIX: parentheses around *fp */
    fp = greet;
    printf("%d\n", fp(2));   /* 84 */
    return 0;
}
The bug: int *fp(int) declares fp as a function that returns int*. Without the parentheses around *fp, the * binds to the return type, not the name. Adding (*fp) makes it a variable (a pointer) whose type is "function taking int, returning int".
P★ — 2024 Final Exam Q6: Duck Simulation (5-part, 50 marks) From: 2024 Final Exam Q6 — 50 marks
What this tests

Struct field access with ->, function pointers in structs, pointer manipulation, malloc, fabs from math.h, and the difference between struct duck's value fields vs pointer fields. Answer each part before revealing the solution.

Given struct (provided on the exam):

#include <stdlib.h>
#include <math.h>

struct duck {
    float position[1];          /* duck's current x-position */
    float velocity[1];          /* positive = right, negative = left */
    struct duck *duck_in_front; /* next duck in queue (NULL if none ahead) */
    int (*quack)(int);          /* function pointer: int quack(int) */
    int alive;                  /* 1 = alive, 0 = dead */
};

Part 0 — 5 marks

What type is the quack field in the struct above? Write out the full type in words and in C syntax.

int (*quack)(int) is a pointer to a function that takes one int parameter and returns int.

Why the parentheses matter: Without them, int *quack(int) would declare a function named quack that returns int* — a completely different thing. The (*quack) forces the * to bind to the name, making it a pointer variable. When you call it via a struct pointer: d->quack(1) — the arrow accesses the struct field, then the (1) calls through the function pointer.

Part 1 — 10 marks

Write a function int same_direction(struct duck *a, struct duck *b) that returns 1 if ducks a and b are moving in the same direction (both positive velocity or both negative velocity). If either duck has velocity 0, return 1. Return 0 otherwise.

int same_direction(struct duck *a, struct duck *b) {
    if (a->velocity[0] == 0.0f || b->velocity[0] == 0.0f) return 1;
    return (a->velocity[0] > 0 && b->velocity[0] > 0) ||
           (a->velocity[0] < 0 && b->velocity[0] < 0);
}
velocity[0] not velocity: The field is declared as float velocity[1] — an array of one element — so you must write velocity[0] to get the float value. Writing just a->velocity gives you a pointer to the array, not the float. Same-sign check: both positive OR both negative means same direction. The zero edge case is handled first as an early return.

Part 2 — 10 marks

Write void update_position(struct duck *d) that updates d->position[0] by adding d->velocity[0]. If d->duck_in_front is NULL, do nothing else and return.

void update_position(struct duck *d) {
    d->position[0] += d->velocity[0];
    if (d->duck_in_front == NULL) return;
    /* Parts 3-5 will extend from here... */
}
Pattern: Always update position first, then check the duck_in_front pointer. The NULL guard prevents dereferencing a null pointer in subsequent parts. Note both fields use [0] because they are declared as float[1] arrays.

Part 3 — 10 marks

Extend update_position(): compute the signed distance between d and d->duck_in_front (front minus self). Use fabs() to get absolute distance. If the absolute distance is less than 1.0f, set d->velocity[0] to 0 — they are too close.

/* Add after the NULL check in update_position: */
float dist = d->duck_in_front->position[0] - d->position[0];
if (fabs(dist) < 1.0f) {
    d->velocity[0] = 0.0f;
    return;
}
fabs vs abs: fabs() is for double/float; abs() is for int. Using abs(dist) on a float would implicitly truncate to int first — a subtle bug. Include <math.h> and compile with -lm. Signed vs absolute distance: The signed distance tells you which side — but the closeness check only cares about magnitude, hence fabs.

Part 4 — 10 marks

Further extend: if d has overtaken duck_in_front (i.e. d->position[0] > d->duck_in_front->position[0]), swap the duck_in_front pointers so d is now in front, and call d->quack(1) to announce the overtake.

/* Add after the closeness check in update_position: */
if (d->position[0] > d->duck_in_front->position[0]) {
    struct duck *tmp = d->duck_in_front;  /* save the overtaken duck */
    d->duck_in_front = NULL;              /* d is now at the front */
    tmp->duck_in_front = d;               /* overtaken duck is now behind d */
    d->quack(1);                          /* call function pointer to announce */
}
Pointer swap pattern: Always save the old pointer in tmp before overwriting it — otherwise you lose access to the overtaken duck and cannot update its duck_in_front. Calling the function pointer: d->quack(1) works because quack is a field in the struct, accessed via ->, then called like any function. No extra dereference is needed — d->quack(1) and (*(d->quack))(1) are equivalent.

Part 5 — 5 marks

Finally: if duck_in_front is not alive (alive == 0), malloc a new dead duck replacement and set d->duck_in_front to point to it. Set its alive = 0 and duck_in_front = NULL. This check should happen before the distance check.

/* Dead duck check — add BEFORE the distance check: */
if (!d->duck_in_front->alive) {
    struct duck *dead = malloc(sizeof(struct duck));
    dead->alive = 0;
    dead->duck_in_front = NULL;
    d->duck_in_front = dead;
    return;
}
Full combined update_position() — all 5 parts together:
void update_position(struct duck *d) {
    /* Part 2: move */
    d->position[0] += d->velocity[0];
    if (d->duck_in_front == NULL) return;

    /* Part 5: dead duck replacement */
    if (!d->duck_in_front->alive) {
        struct duck *dead = malloc(sizeof(struct duck));
        dead->alive = 0;
        dead->duck_in_front = NULL;
        d->duck_in_front = dead;
        return;
    }

    /* Part 3: too close — stop */
    float dist = d->duck_in_front->position[0] - d->position[0];
    if (fabs(dist) < 1.0f) {
        d->velocity[0] = 0.0f;
        return;
    }

    /* Part 4: overtake — rewire pointers and quack */
    if (d->position[0] > d->duck_in_front->position[0]) {
        struct duck *tmp = d->duck_in_front;
        d->duck_in_front = NULL;
        tmp->duck_in_front = d;
        d->quack(1);
    }
}
Order matters: Dead duck check must come before the distance check — dereferencing fields of a dead duck (or a freed duck) could be undefined behaviour. The NULL check (Part 2) must come before everything else. malloc note: In an exam, you are expected to know malloc(sizeof(struct duck)) allocates exactly enough bytes for one duck struct on the heap. The returned pointer is uninitialized except for the two fields you explicitly set.
P5 — State machine using a function pointer array Week 5 Lecture — advanced pattern

Design a simple two-state machine (IDLE, RUNNING) where transitions are handled by a table of function pointers. Each state function should print the current state and return the next state index.

#include <stdio.h>

/* Forward declaration so we can define the array */
int state_idle(int event);
int state_running(int event);

typedef int (*state_fn)(int);

/* State table: index = current state */
state_fn states[2] = { state_idle, state_running };

int state_idle(int event) {
    printf("State: IDLE, event=%d\n", event);
    if (event == 1) return 1;  /* transition to RUNNING */
    return 0;                  /* stay IDLE */
}

int state_running(int event) {
    printf("State: RUNNING, event=%d\n", event);
    if (event == 0) return 0;  /* transition to IDLE */
    return 1;                  /* stay RUNNING */
}

int main(void) {
    int state = 0;  /* start IDLE */
    int events[] = {0, 1, 1, 0, 1};
    for (int i = 0; i < 5; i++) {
        state = states[state](events[i]);
    }
    return 0;
}
Pattern: Each state is a function. The dispatch table states[] maps state indices to state functions. The main loop calls states[current](event) and gets back the next state — no switch statement needed. This is the function pointer dispatch pattern used in embedded systems and protocol parsers.

Key concepts to memorize

Card 1 of 10
Question — click to flip
Answer
Click card to flip • Use buttons to navigate

Test your understanding

Topic 15 Quiz — Function Pointers Score: 0 / 6
1
Which declaration correctly declares fp as a pointer to a function taking two ints and returning int?LO1
multiple choice
2
True or False: fp = add; and fp = &add; are both valid ways to assign a function pointer.LO1
true / false
3
What must a qsort comparison function return when the first argument is less than the second?LO1
multiple choice
4
Fill in the blank: typedef int (___compare_fn)(int, int); — what character goes in the blank to make this a typedef for a function pointer type?LO1
fill in the blank
5
In a qsort comparison function for an int array, what is the correct cast to extract the integer value from the const void * parameter a?LO1
multiple choice
6
What is the purpose of a function pointer dispatch table (array of function pointers)?LO1
multiple choice
0/6
Quiz complete!