aca*_*low 5 c generics integer-arithmetic
我一直在考虑使用C的基本数据类型(例如使用CERT C编码标准)更安全地使用数学运算的方法.到目前为止,我想出了类似的东西:
#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");
}
Run Code Online (Sandbox Code Playgroud)
以上输出类似于:
Integer wrap-around occurred, File: /.../main.c, Line: 41
程序以失败代码退出(假设OS支持).
显然,需要添加额外的操作和类型以及处理带符号的算术,但是我可能会遗漏这个整体方法有什么问题吗?
是否有一种更容易的方式来写这个我忽略了?
这段代码可以是库式的,只是它fprintfs到stderr。相反,您可以找到一种方法将错误直接传达给调用者,然后调用者可以选择优雅地处理它。您可以将它们分开,以便错误报告和退出代码与执行计算并注意到错误的“安静”代码分开。
例如,您会注意到几个 C 函数[1] 返回一个int值,即使它们处理的是字节。这使得它们有“空间”来传达特殊的EOF条件以及所有字节值。
如果您无法在返回值中传达错误条件,则可以使用指针参数将状态传达回调用者。
[1]如fgetc