Reference articles on history, science, culture and more
Encyclopedia

Sentinel value

In-band data value that must be handled specially by computer code

In computer programming, a sentinel value (also referred to as a flag value, trip value, rogue value, signal value, or dummy data) is a special value in the context of an algorithm which uses its presence as a condition of termination, typically in a loop or recursive algorithm.

The sentinel value is a form of in-band data that makes it possible to detect the end of the data when no out-of-band data (such as an explicit size indication) is provided. The value should be selected in such a way that it is guaranteed to be distinct from all legal data values since otherwise, the presence of such values would prematurely signal the end of the data (the semipredicate problem). A sentinel value is sometimes known as an "Elephant in Cairo", due to a joke where this is used as a physical sentinel. In safe languages, most sentinel values could be replaced with option types, which enforce explicit handling of the exceptional case.

Sometimes, it may make more sense to return a null pointer or null value, or when working with option types, return the none/null option.

01Examples

Some examples of common sentinel values and their uses:

02Variants

A related practice, used in slightly different circumstances, is to place some specific value at the end of the data, in order to avoid the need for an explicit test for termination in some processing loop, because the value will trigger termination by the tests already present for other reasons. Unlike the above uses, this is not how the data is naturally stored or processed, but is instead an optimization, compared to the straightforward algorithm that checks for termination. This is typically used in searching.

For instance, when searching for a particular value in an unsorted list, every element will be compared against this value, with the loop terminating when equality is found; however, to deal with the case that the value should be absent, one must also test after each step for having completed the search unsuccessfully. By appending the value searched for to the end of the list, an unsuccessful search is no longer possible, and no explicit termination test is required in the inner loop. After the search, one must decide whether a true match was found, but this test needs to be performed only once rather than at each iteration. Knuth calls the value so placed at the end of the data, a dummy value rather than a sentinel.

Examples

Array

For example, if searching for a value in an array in C, a straightforward implementation is as follows; note the use of a negative number (invalid index) to solve the semipredicate problem of returning "no result":

int find(int arr[], size_t len, int val) { for (int i = 0; i < len; i++) { if (arr[i] == val) { return i; } } return -1; // not found }

However, this does two tests at each iteration of the loop: whether the value has been found and whether the end of the array has been reached. This latter test is what is avoided by using a sentinel value. Assuming the array can be extended by one element (without memory allocation or cleanup; this is more realistic for a linked list, as below), this can be rewritten as:

int find(int arr[], size_t len, int val) { // requires arr has space for len+1 entries int i = 0; arr[len] = val; // add sentinel value while (arr[i] != val) { ++i; } return i < len ? i : -1; }

The test for i < len is still present, but it has been moved outside the loop, which now contains only a single test (for the value), and is guaranteed to terminate due to the sentinel value. There is a single check on termination if the sentinel value has been hit, which replaces a test for each iteration.

It is also possible to temporarily replace the last element of the array by a sentinel and handle it, especially if it is reached:

int find(int arr[], size_t len, int val) { if (len == 0) { return -1; } int last = arr[len - 1]; arr[len - 1] = val; // add sentinel value int i = 0; while (arr[i] != val) { ++i; } arr[len - 1] = last; return arr[i] == val ? i : -1; }

Null values

This is an example of returning null pointers and null options.

import std; using std::nullopt; using std::optional; using std::string; using std::string_view; using std::vector; struct User { private: string name; public: explicit User(string_view name): name{name} {} void setName(string_view s) noexcept { name = s; } [[nodiscard]] string getName() const noexcept { return name; } }; [[nodiscard]] User* findUserByName(vector<User>& users, string_view name) noexcept { for (size_t i = 0; i < users.size(); ++i) { if (users[i].getName() == name) { return &users[i]; } } return nullptr; // Sentinel value: not found } [[nodiscard]] optional<int> findIndex(string_view name, const vector<User>& users) noexcept { for (size_t i = 0; i < users.size(); ++i) { if (users[i].getName() == name) { return i; } } return nullopt; // Sentinel value: not found }
Watch videos about Sentinel valueExplainers and documentaries on YouTube (opens in a new tab)

Sources and credits

This article is adapted from the Wikipedia article Sentinel value, written by its contributors and licensed under CC BY-SA 4.0. Fathomly has changed the layout, removed citation markers, navigation and maintenance notices, and adjusted punctuation. This adapted version is shared under the same license. For references, see the original article.

Fathomly is not affiliated with or endorsed by the Wikimedia Foundation. Spotted a problem? Tell us.