A structured lesson workspace with readable content, hands-on examples, and a clean path to completion.
A function name in an expression decays to a pointer to that function, just as an array name decays to a pointer to its first element. printf and &printf are the same value: the address of the printf function. The & is optional. The types are technically different, but the compiler treats them interchangeably in all practical contexts. You can call through either. You can assign either to a function pointer.
#include <stdio.h>int add(int a, int b) {return a + b;}int main(void) {int (*fp1)(int, int) = add;int (*fp2)(int, int) = &add;printf("add = %p\n", (void *)add);printf("&add = %p\n", (void *)&add);printf("fp1 = %p\n", (void *)fp1);printf("fp2 = %p\n", (void *)fp2);printf("fp1(3,4) = %d\n", fp1(3, 4));printf("fp2(3,4) = %d\n", fp2(3, 4));printf("(*fp1)(3,4) = %d\n", (*fp1)(3, 4));return 0;}
All four pointers hold the same address. All three call syntaxes produce the same result. The (*fp1)(3,4) form explicitly dereferences the function pointer before calling. fp1(3,4) relies on the compiler's implicit dereference. Both are standard. Both are used in real code. Pick one style and be consistent.
Callbacks, dispatch tables, comparators for qsort, signal handlers, virtual function tables in C-based OOP patterns. Function pointers are how C implements polymorphism and event-driven architecture. We dedicate a full lesson to function pointers in the advanced module. For now, know that the function name and its address are interchangeable, and that the & is optional.
Function pointers unlock callback architectures and runtime dispatch in C. They are the mechanism behind qsort's comparator, signal handlers, and plugin systems. We go deep on them later. Next: dynamically allocating a 2D array, where pointer-to-pointer meets heap management.
Finish the lesson once you have worked through the material. This awards ★ 30 XP.