C 合理的实施方式;“安全”;使用泛型的数学运算?

C 合理的实施方式;“安全”;使用泛型的数学运算?,c,generics,integer-arithmetic,C,Generics,Integer Arithmetic,我一直在考虑一种方法,使它更容易安全地使用C的基本数据类型的数学运算(例如,使用)。到目前为止,我已经想出了这样的办法: #include <stdlib.h> #include <stdio.h> #include <limits.h> #define safe_add(x, y) _Generic((x + y), \ unsigned int: safe_ad

我一直在考虑一种方法,使它更容易安全地使用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");
}
#包括
#包括
#包括
#定义安全添加(x,y)通用((x+y)\
unsigned int:safe\u add\u uint\
未签名长:安全添加长\
)(x,y,_文件,_线)
无符号长
安全加长(无符号长x,无符号长y,
常量字符*文件名,整数行(数字)
{
如果(x
上述输出类似于:

发生整数换行,文件:/…/main.c,第41行

程序退出时会显示一个故障代码(假设操作系统支持该代码)

显然,除了处理有符号算术外,还需要添加额外的操作和类型,但是这个整体方法是否存在我可能遗漏的任何问题


是否有一种我忽略的更简单的方法来编写此代码?

此代码可以是库式的,除了它fprintfsstderr。相反,您可以找到一种方法将错误直接传达给调用者,然后调用者可以选择优雅地处理它。您可以拆分这些代码,使错误报告和退出代码与执行计算并注意到错误的“安静”代码分开

例如,您会注意到一些C函数[1]返回一个int值,即使它们处理的是字节。这允许他们在“房间”中传达特殊的EOF条件以及所有字节值

如果无法在返回值中传达错误条件,则可以使用指针参数将状态反馈给调用者


[1] 例如,fgetc

可能(更好?)适合,实际上,我故意省略了errno。我们需要考虑线程安全问题,例如ErrNO、Strutok等。我宁愿避免它们,除非他们自己需要。Bryan Chen:相对于什么?POSIX线程?:是的。Win32线程?:取决于[1]。C11螺纹?:是。C11之前?:视情况而定。[1]