2025-10-18

c functions

part of c programming

functions and routines

  • c functions are not mathematical functions
  • mathematical functions have no side effects and no mutable external state
  • c functions can modify global variables, static storage, or data referenced through pointers
  • the term "routine" or "procedure" may describe c functions more precisely in this regard

caller and callee

  • the caller is the function executing a call expression
  • the callee is the function being invoked
  • after the callee returns, control resumes at the next statement in the caller

call by value

  • in c, all arguments are passed by value
  • when a pointer is passed, the pointer itself is copied, but both caller and callee refer to the same object through that pointer
  • modifications through a pointer affect the same storage visible to both
  • argument values are evaluated before the call and stored in an activation record or registers according to the calling convention

call by contract

  • "call by contract" refers to a programming discipline, not a c language feature
  • the caller ensures preconditions are satisfied before calling
  • the callee assumes valid input and performs no internal validation
  • this reduces branching and simplifies the implementation, at the cost of safety if callers violate preconditions

output

  • c functions can return exactly one value through the return statement
  • functions can modify multiple outputs by receiving pointers and writing to the referenced storage
  • it is common to return an integer status code and place result values in pointer arguments
  • a return value of zero is often used for success, nonzero for failure, though conventions vary

argument order

  • argument order should reflect data flow
  • inputs first, outputs last:

    • string_append(string, suffix, result)
    • list_add(list, value)
  • when the output parameter represents the constructed object, placing it first can improve readability:

    • make_point(out, x, y)

    • make_point(out, x, y, z)

local versus global variables

  • global variables reside in static storage duration and may be accessed by any function
  • local variables reside on the stack and typically allow better compiler optimization
  • locals improve reentrancy and thread safety
  • globals can introduce hidden dependencies and data races
  • performance differences are usually minimal and depend on optimization level, not only storage class

function body structure

  • in modern c, declarations can appear anywhere in a block, but grouping them at the top improves readability and predictability
  • all automatic variables are allocated when the function is entered; lifetime extends until the block ends
  • separating declarations from logic clarifies memory usage and simplifies stack-frame analysis

patterns of function usage

  • allocates and returns memory

    • returns zero pointer on failure or address otherwise
    • may optionally return allocated size through pointer argument
    • cannot use stack or custom allocators directly
  • receives and uses provided memory for input or output
  • allocates and frees memory internally (opaque resource pattern)
  • uses output arguments to return multiple results
  • returns only one scalar result through return value
  • can fail and signal an error code or guarantee no failure
  • modifies input data through pointers when in-place transformation is desired