c++ - 在 C++ 中将有符号整数值转换为可排序、无符号的标准兼容方法是什么?

标签 c++ casting language-lawyer

我有一个用例,我需要将有符号值转换为无符号值,以使值可排序。我需要这个 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/

相关文章:

c++ - C++ 模板只是 "grammar safe"并且首先不是类型安全的?

c++ - 类模板偏特化等价

c++ - 如何检查一个类是否在 C++ 中声明?

java - 类型转换中的模棱两可的行为

java - 将类(class)转换到自制类(class)

c++ - 从相同类型的静态成员进行类内初始化

C++如何使无锁堆栈推送原子

c++ - 有什么方法可以比套接字更快地将数据从 C++ 传输到 Flex/Air?

c++ - 如何从函数指针推导出参数列表?

c++ - 使用 Linux、C++、Kdevelop、gcc、64 位应用程序升级问题