Generic Containers in C: Safe Division Using Maybe. Martin Uecker, 2025-08-10 I discuss the implementation of type and bounds safe generic containers in C. Previously, I discussed a span type, bounds checking using arrays. and a a vector type. This time, I will discuss maybe inspired by Haskell. This type can used to return a value that may not exist, e.g. because an error was encountered during the computation. The following examples shows for a divide function that catches division by zero. static maybe(int) divide(int a, int b) { return (b != 0) ? maybe_just(int, a / b) : maybe_nothing(int); } But careful, there is another error case not checked here! Which is it? As usual, we can define it simply as a macro that expands into a structure, and define simple type constructors. #define maybe(T) struct maybe_##T { bool ok; T value; } #define maybe_just(T, x) (maybe(T)){ .value = (x), .ok = true } #define maybe_nothing(T) (maybe(T)){ .value = (T){ }, .ok = false } In the caller, we can then check whether the value exists or not. int main() { int d = 2; // 0 maybe(int) p = divide(6, d); if (p.ok) { printf("%d\n", p.value); } else { printf("division by zero\n"); fflush(stdout); } return 0; } Can we make this safer to use? In principle, we like to get some error if we try to use the value although it does not exist. For this, we add a macro maybe_value which includes a check. #define maybe_value(T, x) (*({ maybe(T) *_p = &(x); _p->ok ? &_p->value : (void*)0; })) Here, instead of handling the error condition, I create an lvalue that points nowhere in case of an error because it then corresponds to (*({ (void*)0; })), relying on the null sanitizer to transform it into a run-time trap for safety. maybe(int) p = divide(6, d); if (p.ok) { printf("%d\n", maybe_value(p)); } You can find the full example here: Godbolt But as mentioned above, there is another case where integer division has undefined behavior in C. If we divide the smallest representable integer by minus one, the...
First seen: 2025-08-11 06:47
Last seen: 2025-08-11 16:50