liveBook · Manning

Pure function

As explained in Modern C, Third Edition

A pure function is a function whose interactions with the rest of a program occur only through its interface and whose behavior has no other observable effects.

Consider a function that constructs and returns a rational-number value. Its inputs arrive as parameter values; its result leaves through the return value. It does not need to change an object elsewhere in the program. section 10.2.2

 rat rat_get(signed sign, size_t num, size_t denom) [[
    __unsequenced__]] {
   rat ret = {
     .sign = (sign < 0),
     .num = num,
     .denom = denom,
   };
   return ret;
 }

The constructor assembles a local `rat` value and returns it. Its `[[__unsequenced__]]` annotation states a property the function definition must satisfy; the annotation does not make an impure definition pure. section 10.2.2 section 16.3

A pure function has no effect other than returning a value, and that value depends only on its arguments. Changing a local value while computing the result is compatible with this rule. The question is whether a call reads or changes state outside its interface. section 10.2.2

A function is not pure if it:

  • reads changeable program state by means other than its arguments, including a changeable global object; section 10.2.2
  • modifies a global object or retains persistent internal state between calls; section 10.2.2
  • performs input or output. section 10.2.2

TAKEAWAY: Express small tasks as pure functions when possible. Their behavior is local enough for a reader to follow and for an optimizer to reason about: once arguments are available, a call can be moved relative to other work, provided its result is ready when needed. Purity alone is not a reason to trade correctness for performance. section 10.2 section 10.2.2 section 16.5

Returning a transformed value

A rational-number operation can take `rat` values, calculate a normalized sum or product, and return another `rat`. Assignments to its local copies do not by themselves alter the caller’s objects. By contrast, a swap that changes the caller’s two `double` objects through pointers is not pure. section 10.2.2 section 11.0

In C23, `[[unsequenced]]`—or the macro-safe spelling `[[__unsequenced__]]`—can communicate the relevant guarantee to callers even when only a declaration is visible. For a function without pointer parameters or a pointer return, the annotated function is pure: its result depends on argument values. With pointers, the attribute has a broader meaning that permits limited interaction through objects visible via those pointers; do not equate every annotated pointer-taking function with the simple pure-function model. section 10.2.3 section 16.3

Verify the guarantee before annotating a definition. In particular, an `[[unsequenced]]` function must not read nonconstant global variables or system state. Floating-point code deserves care because a changeable rounding mode can affect a result without appearing among the function’s arguments. section 16.3

How Modern C, Third Edition covers it

How deep it goes
Defines purity by result dependency and effects, lists disqualifying state interactions, and qualifies the C23 annotation for pointer-taking functions.
Examples
Uses value-returning rational-number operations, a pointer-based swap, and floating-point rounding state to test the boundary.
What it assumes
Assumes familiarity with C functions, parameters, return values, and global objects; defines purity explicitly before examining attribute constraints.
What you can do after
Build it from scratch: write small value-returning functions, check their state dependencies and effects, then annotate qualifying C23 definitions.
How it connects
Connects pure functions to global variables, pointers, compiler optimization, `inline`, and C23 `[[unsequenced]]` attributes.

Also explained in

Compare how 19 books explain pure function →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Modern C, Third Edition. The section links point to the parts of the book it draws on.