我有一个用例,我需要将有符号值转换为无符号值,以使值可排序。我需要这个 char
, short
, int
, long
, 和 long long
我所说的可排序,是指 signed
输入 X,如果 (a < b)
然后转换为未签名的 converted(a) < converted(b)
.请注意,在许多情况下,从负数 signed
转换值直接到 unsigned
value 将使值大于0
并打破这个限制(补码实现)
char
的最简单想法是:
unsigned char convert(char x)
{
return (unsigned char)(x ^ 0x80); // flip sign to make it sortable
}
但这似乎是 undefined behavior
.
虽然可以转换为更大的类型,但添加类型 MIN 值,然后转换为 unsigned
类型,我不确定这是否更合规,并且不适用于 long long
没有任何 undefined behavior
怎么办?适用于所有类型?
使用 memcpy
转换似乎是安全的,但不清楚如何以合规的方式维护排序顺序。
(请注意,这类似于:No compliant way to convert signed/unsigned of same size,除了我需要保持排序顺序的结果)
最佳答案
你做错了,因为翻转有符号值的符号位实际上并没有定义。
让我们使用两位类型:
00 01 10 11 Order for unsigned 0 1 2 3
10 11 00 01 Order for 2s complement -2 -1 0 1
11 (10 00) 01 Order for sign-magnitude -1 (-0 +0) 1
10 (11 00) 01 Order for 1s-complement -1 (-0 +0) 1
您要做的是转换为无符号(始终定义为保值,带环绕),然后添加一个偏差,使最负数变为 0:
int x = whatever;
unsigned r = (unsigned)x - (unsigned)INT_MIN;
注意:有符号溢出没有定义,所以我们避免了有符号类型。
当然,如果无符号类型的值少于有符号类型的值,这也无济于事, 通常是允许的,但对于 char
则不行。
如果要将负 0 保留为负数,则需要特别小心。
关于c++ - 在 C++ 中将有符号整数值转换为可排序、无符号的标准兼容方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33569303/