Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clarify undefined behavior if target isn't in the list #26

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,10 @@ i.e. the address of the `next` element in the current `list_item`.
When the pointer to the list item `*p` equals `target`, we exit the search
loop and remove the item from the list.

(If `target` isn't in the list, and isn't NULL, then `find_indirect` will
dereference `NULL` and crash. If this case can happen, check if `*p == NULL`
inside the loop and handle this error appropriately.)


## How does it work?

Expand Down Expand Up @@ -254,6 +258,8 @@ void remove_elegant(list *l, list_item *target)
}
```



### Implementing `insert_before()`

Using `find_indirect()`, it is straightforward to implement `insert_before()`:
Expand All @@ -269,9 +275,8 @@ void insert_before(list *l, list_item *before, list_item *item)

A particularly beautiful outcome is that the implementation has consistent
semantics for the edge cases: if `before` points to the list head, the new item
will be inserted at the beginning of the list, if `before` is `NULL` or invalid
(i.e. the item does not exist in `l`), the new item will be appended at the
end.
will be inserted at the beginning of the list. If `before` is `NULL`, the
new item will be appended at the end of the list.


## Conclusion
Expand Down
10 changes: 6 additions & 4 deletions src/list.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,11 @@ void remove_cs101(list *l, list_item *target)
* This is a linear O(n) search.
*
* @param l A list of integers
* @param target The list item to find
* @param target The list item to find. Must exist in the list, or be NULL,
otherwise undefined behavior.
* @return Pointer to the `next` pointer of the item that precedes
* `target`, or `head`. Pointer to the last `next` field in the list
* if `target` is not in `l`.
* if `target` is NULL.
*/
static inline list_item **find_indirect(list *l, list_item *target)
{
Expand All @@ -51,8 +52,9 @@ void remove_elegant(list *l, list_item *target)
* @param l A list of integers
* @param before Pointer to item before which the new item should be inserted.
* If `before` points to the list head, the new item will be
* inserted at the beginning; if `before` is NULL or invalid,
* the item will be appended at the the end of the list
* inserted at the beginning; if `before` is NULL,
* the item will be appended at the the end of the list;
* otherwise undefined behavior.
* @param item The item to insert
*/
void insert_before(list *l, list_item *before, list_item *item)
Expand Down