I've been thinking about a way to make it easier to safely use math operations with C's basic datatypes (e.g. using the CERT C coding standard). So far, I've come up with something like this:
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
#define safe_add(x, y) _Generic((x + y), \
unsigned int: safe_add_uint, \
unsigned long: safe_add_ulong \
)(x, y, __FILE__, __LINE__)
unsigned long
safe_add_ulong(unsigned long x, unsigned long y,
const char* filename, int line_num)
{
if (x < ULONG_MAX - y)
return x + y;
else {
fprintf(stderr,
"Integer wrap-around occurred, File: %s, Line: %d\n",
filename, line_num);
exit(EXIT_FAILURE);
}
}
unsigned int
safe_add_uint(unsigned int x, unsigned int y,
const char* filename, int line_num)
{
if (x < UINT_MAX - y)
return x + y;
else {
fprintf(stderr,
"Integer wrap-around occurred, File: %s, Line: %d\n",
filename, line_num);
exit(EXIT_FAILURE);
}
}
int
main()
{
/*
* usual arithmetic conversions results in this calling
* the uint version of safe_add...
*/
safe_add(2000000000, 3000000000u));
printf("We shouldn't get here...(unless unsigned int uses more than 32 bits)\n");
}
Output of the above would be something similar to:
Integer wrap-around occurred, File: /.../main.c, Line: 41
and the program exits with a failure code (assuming the OS supports that).
Obviously, additional operations and types need to be added as well as handling signed arithmetic, but are there any problems with this overall method that I may be missing?
Is there perhaps an easier way to write this that I've overlooked?