2024-07-03

c functions

c functions are not mathematical functions

  • mathematical functions can not modify their context/environment
  • the term "routine" may be technically more appropriate

caller and callee

the caller is the function that makes a call to another function. the other called function is the callee.

call by value

call by value signifies that function arguments are duplicated for use by the called function. this guarantees that modifications to the arguments within the callee do not affect the original variables in the caller scope. consequently, there is no need to consider whether parallel code might alter the argument values during their usage.

call by contract

call by contract is a design pattern mandating that the caller ensures the callee can accept the provided arguments. in other words, it is incumbent upon the caller to verify that the arguments align with the function domain. as a consequence, functions require less abstraction and perform only the essential operations. with call by contract, functions do not validate or reject invalid data that may have been passed.

output

  • functions can return one value
  • functions can modify data via pointer arguments
  • the single return value can be used to return an error identifier after writing result values via pointer arguments

    • rationale for using the return value for the error status: there is always only one error status but multiple result values may be possible

argument order

for example, acted-on arguments first, and output arguments last:

  • string_append :: a b result
  • list_add :: list value

especially when the argument count is variable, it may be preferable to put the output arguments first:

  • make_point :: out x y
  • make_point :: out x y z

local versus global variables

using globals might save declaration overhead, but access of a local is often faster because the compiler can better predict where it will be modified and prepare to cache.

performance example

  • global

    • 0m10.745s
    • 0m10.739s
  • local

    • 0m9.931s

    • 0m9.940s

function body structure

all stack allocations are made at the beginning of a function call, regardless of where they are declared in the code of the function body. having all declarations grouped together at the beginning may make it clearer what is actually happening. additionally, having all declarations at the top may make finding declarations easier than searching them when they are scattered throughout the function body.

patterns of function usage

  • allocates and returns memory

    • can return null for failure or an address otherwise
    • need to return size if size is determined in function
    • con: can not use stack allocated memory, can not use custom allocator
  • receives and uses memory for input or output
  • allocates and frees memory
  • has output arguments
  • has only the return argument
  • can fail and return error code or uses only non-failing features
  • modifies input