You should re-order your includes: Always include the header you are implementing first, then all other headers, sorted for consistency (use the IDE's sorting-macro).
That way, you will know that your header is self-sufficient and you didn't forget a crucial dependency.There's
abort()
for abnormal termination. Consider writing a helper-function if you need to output an error-message and abort in multiple places:static void die(const char* message);
All your internal functions should not have external linkage, for performance and correctness reasons: Mark them
inline
.Putting
next
first is more common, and possibly slightly more efficient. Also, for a single valuevalue
is more idiomatic thandata
.Is there any reason why your typedef-name and struct-tag aren't quite equal? That's ittitating.
node_create
is a waste: It's literally more work to read, write, and use it than leaving the single use inline.
As a rule of thumb, extracting 2 lines into their own function is a net loss of readability. Exceptons are often-used pieces of code.Actually, that can be generalized to all your internal functions, with the possible exception of
node_delete
, which is marginal.There areThere are two kinds ofkinds of precondition-checks:
- Sanity checks, verifying that the programs logic is sane. These are normally disabled in a release build for performance reasons, and use
assert()
. - Tests of untrusted input. How far you can/should/must trust an API's user must be decided in each case. It's your task as API-designer to decide how much you should penalize your users to catch egregious abuse even in release-mode, and whether there's also a debug-mode.
But there's no excuse for making your internal helper-functions re-assert preconditions even in release-mode.
- Sanity checks, verifying that the programs logic is sane. These are normally disabled in a release build for performance reasons, and use
As you are using C99 (see
<stdbool.h>
), you can use compound-literals to set all members of a struct-type comfortably even after initialization.void stack_push(StackCDT *s, StackElement value) { Node *new = malloc(sizeof *new); *new = (Node){s->top, value}; if(!new) die("Failed to allocate a new node."); s->top = new; }