如何将有符号整数转换为C中对应的无符号整数?
我想定义一个C宏
#define TO_UNSIGNED(x) (...) ,它采用有符号整数x(可以是:signed char,short,int,long,long long或其他任何东西,甚至长于long long的东西),并将x转换为相同大小的相应无符号整数类型. 可以假设有符号整数使用二进制补码表示.因此,要转换任何值(正或负),应采用其二进制补码表示,并且应将其解释为相同大小的无符号整数. 我假设使用了一个相当现代的优化编译器,它可以消除未使用的分支,例如,如果sizeof(X)< 4? f(Y):执行g(Z),然后不评估X,并且仅生成并评估f(Y)或g(Z)中的一个. 解决方法
我会咬人,但我不得不说这更像是宏观黑客的精神,而不是因为我认为这样的宏是有用的.开始:
#include <stdlib.h> #include <stdio.h> #define TO_UNSIGNED(x) ( (sizeof(x) == 1) ? (unsigned char) (x) : (sizeof(x) == sizeof(short)) ? (unsigned short) (x) : (sizeof(x) == sizeof(int)) ? (unsigned int) (x) : (sizeof(x) == sizeof(long)) ? (unsigned long) (x) : (unsigned long long) (x) ) // Now put the macro to use ... short minus_one_s() { return -1; } long long minus_one_ll() { return -1LL; } int main() { signed char c = -1; short s = -1; int i = -1; long int l = -1L; long long int ll = -1LL; printf("%llxn",(unsigned long long) TO_UNSIGNED(c)); printf("%llxn",(unsigned long long) TO_UNSIGNED(s)); printf("%llxn",(unsigned long long) TO_UNSIGNED(i)); printf("%llxn",(unsigned long long) TO_UNSIGNED(l)); printf("%llxn",(unsigned long long) TO_UNSIGNED(ll)); printf("%llxn",(unsigned long long) TO_UNSIGNED(minus_one_s())); printf("%llxn",(unsigned long long) TO_UNSIGNED(minus_one_ll())); return 0; } 宏使用三元比较运算符?:来模拟所有已知有符号整数大小的switch语句. (这应该捕获适当的无符号整数和从< stdint.h>中键入的typedef.它适用于表达式.它也接受浮点数,虽然不如我期望的那样.) 稍微复杂的printfs显示负数被扩展为源整数的原始大小. 编辑:OP正在查找一个宏,该宏返回与源类型长度相同的无符号类型的表达式.上面的宏没有这样做:因为三元比较的两个替代值被提升为一个公共类型,所以宏的结果总是最大的类型,即unsigned long long. 可以使用纯宏解决方案实现不同类型的分支,这样在预处理之后,编译器只能看到一种类型,但是预处理器不知道类型,因此这里不能使用sizeof,这排除了这样的宏. 但是对于我的(弱)防御,我会说如果将宏的无符号long long结果的值赋给适当的无符号类型(即简称unsigned short),则该值永远不应被截断,因此宏可能有一些用处. 编辑II:既然我在another question中偶然发现了C11 _Generic关键字(并且已经安装了支持它的编译器),我可以提出一个有效的解决方案:以下宏实际上返回了正确类型的正确值: #define TO_UNSIGNED(x) _Generic((x), char: (unsigned char) (x), signed char: (unsigned char) (x), short: (unsigned short) (x), int: (unsigned int) (x), long: (unsigned long) (x), long long: (unsigned long long) (x), default: (unsigned int) (x) ) _Generic选择在编译时解析,并且没有在超大int类型中生成中间结果的开销. (一个真实世界的宏应该包含自己的无符号类型以进行空转.另请注意,我必须显式包含signed char,只是char不起作用,即使我的字符已签名.) 它需要一个最近的编译器来实现C11或至少它的_Generic关键字,这意味着这个解决方案不是非常便携,但是,see here. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |