在 C/C++ 中签名扩展数字的最佳方式是什么
What is the best way to sign extend a number in C/C++
我有一个 10 位有符号值。它实际上是一个 10 位颜色值,我想将其转换为 int
.
这 10 位将被解释为更大 int
中的有符号值,其中其他位为零。
我可以想到 3 种方法,如下所示:
#include <stdio.h>
void p(int v)
{
printf("\t%d", v);
}
int main()
{
for (int i = -2; i < 3; ++i)
{
unsigned int u = i & 0x3ff;
int v;
// method 1: test the bit
v = u;
if (u & 0x200) v = v ^ -0x400;
p(v);
// method 2: shift
v = u<<(sizeof(int)*8-10);
v >>= (sizeof(int)*8-10);
p(v);
// method 3: use sign extend
v = (signed char)(u >> 2);
v <<= 2;
v |= u;
p(v);
printf("\n");
}
return 0;
}
还有更好的方法吗?经常有这样的小问题。
感谢任何意见。
更新
再添加两个方法。 @cruz-jean建议的第一个是位域,第二个是gcc在编译位域后建议的
// method 4: bit fields
struct { int v:10; } f;
f.v = u;
v = f.v;
// method 5: sign extend short
v = (signed short)(u << 6);
v >>= 6;
有趣的是,MSVC 似乎将#4 编译成#2,而 gcc 将#4 编译成#5。
方法5看起来不错。
您可以声明一个 10 位带符号的位域帮助程序类型,并以 int
:
的形式访问该值
struct signed_10_bit
{
int val : 10;
};
int some_10_bit_num = 0x3ff;
int extended = signed_10_bit{ some_10_bit_num }.val;
另一个尝试:
v = u | (0 - (u&0x200));
适用于 shift 较慢的 cpus。
我有一个 10 位有符号值。它实际上是一个 10 位颜色值,我想将其转换为 int
.
这 10 位将被解释为更大 int
中的有符号值,其中其他位为零。
我可以想到 3 种方法,如下所示:
#include <stdio.h>
void p(int v)
{
printf("\t%d", v);
}
int main()
{
for (int i = -2; i < 3; ++i)
{
unsigned int u = i & 0x3ff;
int v;
// method 1: test the bit
v = u;
if (u & 0x200) v = v ^ -0x400;
p(v);
// method 2: shift
v = u<<(sizeof(int)*8-10);
v >>= (sizeof(int)*8-10);
p(v);
// method 3: use sign extend
v = (signed char)(u >> 2);
v <<= 2;
v |= u;
p(v);
printf("\n");
}
return 0;
}
还有更好的方法吗?经常有这样的小问题。
感谢任何意见。
更新
再添加两个方法。 @cruz-jean建议的第一个是位域,第二个是gcc在编译位域后建议的
// method 4: bit fields
struct { int v:10; } f;
f.v = u;
v = f.v;
// method 5: sign extend short
v = (signed short)(u << 6);
v >>= 6;
有趣的是,MSVC 似乎将#4 编译成#2,而 gcc 将#4 编译成#5。
方法5看起来不错。
您可以声明一个 10 位带符号的位域帮助程序类型,并以 int
:
struct signed_10_bit
{
int val : 10;
};
int some_10_bit_num = 0x3ff;
int extended = signed_10_bit{ some_10_bit_num }.val;
另一个尝试:
v = u | (0 - (u&0x200));
适用于 shift 较慢的 cpus。