2026-04-06

c return status

type

typedef struct {
  int id;
  char* group;
} status_t;

id == 0 denotes success. id != 0 denotes failure.

a status is identified by (group, id).

the canonical success value is:

{ status_id_success, status_group_undefined }

applicability

only functions that can fail return status_t.

functions that cannot fail do not return status_t.

this is a semantic partition, not a stylistic choice.

local carrier

a fallible function declares:

status_declare;

this establishes a success-initialized local status.

control

assignment

status_set(group_id, status_id);

transfer

status_goto;
status_set_goto(group_id, status_id);

control transfers to:

exit:

return

status_return;
status_i_return;

propagation

status-returning callee

status_require(callee(...));

semantics:

  • assign result to status
  • if status.id != 0, transfer to exit

integer-returning callee

status_i_require(callee(...));

semantics:

  • assign result to status.id
  • if status.id != 0, transfer to exit

group assignment is the caller's responsibility.

direct return

status_require_return(callee(...));

cleanup

a function may define a single convergence point:

exit:

both normal and failure paths may reach it.

resource state

each owned resource has a neutral value representing "not owned".

the resource variable itself encodes ownership state.

no auxiliary tracking variables are introduced if the resource variable suffices.

preparation pattern

for each resource:

  • initialize variable to its neutral value before acquisition
  • acquisition moves it to owned state
  • no other state is relevant

cleanup rule

at exit::

  • release each resource whose variable denotes ownership
  • do not release resources in neutral state
  • do not release any resource more than once

cleanup is expressed solely in terms of resource variables.

invariants

  • status.id == 0 implies success
  • status.id != 0 implies failure
  • (group, id) identifies the failure
  • propagation preserves (group, id) unless reassigned
  • cleanup correctness depends only on resource variables, not on auxiliary flags

minimal correctness criterion

the convention is correct if and only if:

  • all fallible functions return status_t
  • all failure paths transfer to a single exit: or return immediately
  • all owned resources are released exactly once at exit:
  • resource ownership is encoded only in the resource variables themselves