看起来没有通用的解决方案能够支持所有可能大小的整数。
对于一个硬编码类型列表,我能够使用C语言中的__builtin_choose_expr
和C++中的重载函数使其工作。这是解决方案: https://github.com/pts/to-unsigned/blob/master/to_unsigned.h
相关的C代码如下:
__builtin_choose_expr(__builtin_types_compatible_p(__typeof(x), unsigned char), (unsigned char)(x), \
__builtin_choose_expr(__builtin_types_compatible_p(__typeof(x), char), (unsigned char)(x), \
__builtin_choose_expr(sizeof(x) == sizeof(char), (unsigned char)(x), \
__builtin_choose_expr(__builtin_types_compatible_p(__typeof(x), unsigned short), (unsigned short)(x), \
__builtin_choose_expr(__builtin_types_compatible_p(__typeof(x), short), (unsigned short)(x), \
__builtin_choose_expr(sizeof(x) == sizeof(short), (unsigned short)(x), \
__builtin_choose_expr(__builtin_types_compatible_p(__typeof(x), unsigned), (unsigned)(x), \
__builtin_choose_expr(__builtin_types_compatible_p(__typeof(x), int), (unsigned)(x), \
__builtin_choose_expr(sizeof(x) == sizeof(int), (unsigned)(x), \
__builtin_choose_expr(__builtin_types_compatible_p(__typeof(x), unsigned long), (unsigned long)(x), \
__builtin_choose_expr(__builtin_types_compatible_p(__typeof(x), long), (unsigned long)(x), \
__builtin_choose_expr(sizeof(x) == sizeof(long), (unsigned long)(x), \
__extension__ __builtin_choose_expr(__builtin_types_compatible_p(__typeof(x), unsigned long long), (unsigned long long)(x), \
__extension__ __builtin_choose_expr(__builtin_types_compatible_p(__typeof(x), long long), (unsigned long long)(x), \
__extension__ __builtin_choose_expr(sizeof(x) == sizeof(long long), (unsigned long)(x), \
(void)0))))))))))))))))
在 C11 中,可以使用等效的 _Generic
结构替代 __builtin_choose_expr
+ __builtin_types_compatible_p
,前提是编译器支持它。
C++11 有 std::make_unsigned,并且其在 libstdc++ 中的实现明确枚举了它所知道的整数类型,类似于我对 TO_UNSIGNED
的 C++ 实现。
x
的二进制补码表示,并将其解释为相同大小的无符号整数。 - ptssizeof
。 - Paul Hankin#define ADD_WRAP(x, y) ((typeof(x))(TO_UNSIGNED(x) + TO_UNSIGNED(y)))
,它类似于使用gcc -fwrapv
的#define ADD_WRAP(x, y) ((x) + (y))
,即与无符号类型相同的整数环绕。 - ptssizeof
进行评估。如果预处理器可以将sizeof
评估为十进制数,则可以使用连接运算符##
将TO_UNSIGNED(x)
转换为TO_UINT1(x)
、TO_UINT2(x)
等等。使用sizeof
并依赖于优化编译器来删除常量 false 条件的死分支的解决方案不符合您的类型要求。匿名人士是正确的:预处理器中没有sizeof
。 - M Oehm