我有一个长度为5位的值。 4位确定数字,第5位确定符号,通过保持-16和+15之间的任何值。如何在C#中实现从恒定位宽扩展的符号?我知道在C中,我可以使用类似下面的内容来完成此任务:
int x; // convert this from using 5 bits to a full int
int r; // resulting sign extended number goes here
struct {signed int x:5;} s;
r = s.x = x;
如何在C#中执行类似的操作?
答案 0 :(得分:2)
你的意思并不是很清楚,但可能就像这样简单:
int fiveBits = normal & 0x1f;
反之亦然:
int normal = fiveBits < 16 ? fiveBits : fiveBits | -32;
如果您可以建议一些原始输入和所需输出,那将有所帮助。
答案 1 :(得分:2)
我知道这是一个老问题,但对于未来的搜索者,我有更多的信息。
C#不支持自定义位宽,但它支持二进制操作和getter / setter,这使得添加兼容层变得相对容易。例如,如果要将原始数据存储在字节_num中,但希望能够使用标准C#sbyte与其进行交互,则可以使用以下命令:
byte _num;
sbyte num {
get
{
return (sbyte)(((_num & 0x10) << 3) | (_num & 0x0F));
}
set
{
_num = (byte)((value & 0x0F) | ((value & 0x80) >> 3));
}
}
这种shell在与低级固件或嵌入式项目交互时特别有用。
答案 2 :(得分:1)
执行左移,然后是算术右移,将符号位移动到高位然后再移回。算术右移将为您执行符号扩展。
当然这取决于是否有一个有效的算术移位操作。抽象的C语言没有(它的实现定义是否有效),但大多数实现都有。我不确定C#,但我猜它有一个。
答案 3 :(得分:1)
我只是编写一个C函数(因为我真的不知道C#),它会使用我知道在C#中可用的操作来完成这项工作。
int five_bit_to_signed(int five_bit) {
int sh = (sizeof(int)*8)-5;
int x = five_bit << sh; // puts your sign bit in the highest bit.
return x >> sh; // since x is signed this is an arithmatic signed shift
}
答案 4 :(得分:0)
从您的问题来看,您似乎希望拥有一个可以轻松转换为int
类型的结构:
struct FiveBit
{
public int bits;
public static implicit operator int(FiveBit f)
{
return (f.bits & 0x10) == 0 ? f.bits : f.bits | -32;
}
public static implicit operator FiveBit(int r)
{
return new FiveBit() { bits = r & 0x1f };
}
}
以下是一个使用示例:
class FiveBitTest
{
static void Main(string[] args)
{
FiveBit f = new FiveBit();
int r; // resulting sign extended number goes here
f.bits = 0;
r = f;
Console.WriteLine("r = {0}, f.bits = 0x{1:X}", r, f.bits);
f.bits = 0x1f;
r = f;
Console.WriteLine("r = {0}, f.bits = 0x{1:X}", r, f.bits);
r = -2;
f = r;
Console.WriteLine("r = {0}, f.bits = 0x{1:X}", r, f.bits);
}
以上的输出是:
r = 0, f.bits = 0x0
r = -1, f.bits = 0x1F
r = -2, f.bits = 0x1E