Skip to main content

API Boundaries

beginner14 min readLesson 65 of 148

A module is a promise: the header declares what callers may use, the .c decides how it works.

The one-file preview of the two-file world

This course's sandbox compiles a single file, so we rehearse the multi-file pattern inside it. The rules are exactly the ones a real geom.h + geom.c project follows:

/* ---- the CONTRACT (what geom.h would say) ---- */
int stack_push(int v);          // callers may call this
int stack_pop(int *out);        // callers may call this

/* ---- the IMPLEMENTATION (what geom.c would contain) ---- */
static int data[16];            // private: callers never touch this
static int count = 0;           // private state

int stack_push(int v) {
    if (count == 16) return 0;  // full: report failure
    data[count++] = v;
    return 1;
}

int stack_pop(int *out) {
    if (out == NULL || count == 0) return 0;
    *out = data[--count];
    return 1;
}

What makes it a boundary

  • public: functions a caller is allowed to call โ€” declared first, no static
  • private: static data and helpers โ€” invisible outside the module
  • The header never contains static state or function bodies; it is pure promise.

The discipline the compiler enforces

Callers can only reach the public functions. When the private representation changes (array size, algorithm), no caller's code changes โ€” the boundary held. That property is the entire point of modules.

Prototype-then-define inside one file

The same contract/check shape works inside one translation unit: declare the public functions at the top (that's the "header" region), define them below. gcc checks every call against the declaration, exactly as it would against a real header.

Now practice

API DisciplineModules with private state reached only through public functions.3 challenges ยท ยท ~16 min