gpt4 book ai didi

C 将有符号转换为无符号并保持精确位

转载 作者:行者123 更新时间:2023-11-30 18:48:42 24 4
gpt4 key购买 nike

编辑:我将示例更新为 C。我特别关心 C 而不是 C++(很抱歉造成困惑,请参阅下面的情况)。

我正在寻找一种安全的方法来将有符号整数转换为无符号整数,同时始终在转换之间保持完全相同的位模式。据我了解,简单的强制转换具有未定义或依赖于实现的行为,因此依赖它是不安全的(下面的情况 A)。但是像 OR 这样的按位运算符(下面的情况 B)呢?可以使用按位或来安全地将有符号转换为无符号吗?反过来呢?

示例:

#include <stdio.h>

int main() {
// NOTE: assuming 32bit ints
// example bit pattern: 11111111110001110001001111011010
// signed int value: -3730470
// unsigned int value: 4291236826

// example 1
// signed -> unsigned
int s1 = -3730470;
unsigned int u1a = (unsigned int)s1;
unsigned int u1b = (unsigned int)0 | s1;

printf("%u\n%u\n", u1a, u1b);

// example 2
// unsigned -> signed
unsigned int u2 = 4291236826;
int s2a = (int)u2;
int s2b = (int)0 | u2;

printf("%i\n%i\n", s2a, s2b);
}
<小时/>

情况:我正在写一个PostgreSQL C-Language function/extension 添加 popcount 功能 ( my first attempt code here )。 PostgreSQL 不支持无符号类型 ( ref )。我发现的所有计算 popcount 的有效方法都需要无符号数据类型才能正常工作。因此,我必须能够将有符号数据类型转换为无符号数据类型而不更改位模式。

题外话:我确实意识到替代解决方案是使用 PostgreSQL 位字符串 bitvarbit 数据类型而不是整数数据类型,但就我的目的而言,整数数据类型更易于使用和管理。

最佳答案

a safe way to convert a signed integer to an unsigned integer while always maintaining the exact same bit pattern between conversions

即使 int 是罕见的非 2 补码,union 也会按如下方式工作。只有在非常期望的平台上(在硅墓地里滴答作响),其中 INT_MAX == UINT_MAX 才会出现问题。

union {
int i;
unsigned u;
} x = { some_int };
printf("%d\n", some_int);
printf("%u\n", x.u);

但是,如果可以将自己限制为常见的 2 的补码 int,那么下面的内容就足够了。

unsigned u = (unsigned) some_int;
<小时/>

But what about bit-wise operators like OR (case B below)?
Can bit-wise OR be used to safely convert signed to unsigned?

以下 | 就像由于整数提升而隐藏的转换:

If an int can represent all values of the original type (as restricted by the width, for a bit-field), the value is converted to an int; otherwise, it is converted to an unsigned int. C11dr §6.3.1.1 3

int s1 = -3730470; 
unsigned int u1b = (unsigned int)0 | s1;
// just like
= (unsigned int)0 | (unsigned int)s1;
= (unsigned int)s1;
<小时/>

What about the reverse?

如果值可以用 [0...INT_MAX] 表示,则将 unsigned int 转换为 signed int 是明确定义的。将超出 int 范围的 unsigned 转换为 int 是...

either the result is implementation-defined or an implementation-defined signal is raised. §6.3.1.3 3

最好使用无符号类型进行位操作。
下面的代码通常可以按预期工作,但不应用于稳健编码。

// NOTE: assuming 32bit ints, etc.
unsigned int u2 = 4291236826;
int s2a = (int)u2; // avoid this

替代方案

int s2a;
if (u2 > INT_MAX) {
// Handle with some other code
} else {
s2a = (int) u2; // OK
}
<小时/>

顺便说一句:最好将 u 附加到无符号常量(例如 4291236826),以向编译器传达确实是一个无符号常量,而不是long long 如 4291236826。

unsigned int u2 = 4291236826u;

关于C 将有符号转换为无符号并保持精确位,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44954193/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com