将Int32转换为24位有符号整数

3

我需要将一个Int32值转换为3字节(24位)整数。字节序保持不变(小端),但我无法找出如何适当地移动符号。这些值已经被限制在正确的范围内,我只是无法想出如何将4个字节转换为3个字节。使用C# 4.0。这是为了硬件集成,所以我必须有24位的值,不能使用32位。


你打算用什么类型来存储24位整数? - The Scrum Meister
一个字节数组就可以了。我将通过串行连接输出这3个字节,只要我能把它转换成字节,我就可以继续了。 - drharris
第三行代码不会有任何作用(i&0xffffff始终为正)。此外,您可能希望遵循Joe答案的第二部分,该部分适用于具有不同字节序的系统。您现在拥有的代码可以工作,但如果您尝试在PowerPC或MIPS上运行它,则会以异常方式中断。 - Jeremiah Willcock
抱歉,我的实际代码涉及在负数时设置一个 bool 标志。我忽略了第二行会使它变成正数,因此第三行永远不会激活的事实。重点是测试原始数字是否为负数。我将相应地更新答案。我已经考虑了字节序,但我会在解决方案中做出注释,建议你也这样做。 - drharris
我只是完全删除了我的附言。任何有兴趣的人都应该阅读答案。假设32位值已经限制在24位整数的范围内,由于二进制补码,负号将始终传递给24位。剩下的就是在检索字节数组时检查字节顺序。我试图使事情过于复杂化了。 :) - drharris
2个回答

3
发现这个:http://bytes.com/topic/c-sharp/answers/238589-int-byte
int myInt = 800;
byte[] myByteArray = System.BitConverter.GetBytes(myInt);

听起来你只需要获取数组的最后3个元素。

编辑:

正如Jeremiah指出的那样,你需要做一些像这样的事情

int myInt = 800;
byte[] myByteArray = System.BitConverter.GetBytes(myInt);

if (BitConverter.IsLittleEndian) {
    // get the first 3 elements
} else {
    // get the last 3 elements
}

1
什么缺陷?需要一个小端系统吗?所有写入字节数组的解决方案似乎都需要进行字节序检查;在32位字中执行v & 0xFFFFFF,无需知道它以何种方式表示为字节。 - Jeremiah Willcock
再仔细查看文档后,无论系统如何,“BinaryReader”和“BinaryWriter”始终是小端的。此外,在http://snipplr.com/view/15179/adapt-systembitconverter-to-handle-big-endian-network-byte-ordering-in-order-to-create-number-types-from-bytes-and-viceversa/上有一个解决方案,允许设置字节序。 - Jeremiah Willcock
看了你回答的最新更改,我认为它还是反过来了:对于小端,你想要前3个元素,对于大端,你想要后3个元素。 - Jeremiah Willcock
啊,好的,我现在明白了。我已经更新了我的答案,希望现在是字节序正确的 :) - Joe
那是因为我花了大约5分钟写我的评论,而你已经发布了2个! :) 你太快了。好的,怎么样? - Joe
显示剩余5条评论

3
如果您想进行转换,只需删除四字节数字的最高字节。使用二进制补码表示将正确处理符号。如果您想将24位数字保留在Int32变量中,可以使用v & 0xFFFFFF仅获取低24位。我看到了您关于字节数组的评论:如果数组中有空间,请写入数字的所有四个字节,并仅发送前三个字节;但这仅适用于小端系统。

谢谢提供信息。我仍然不确定符号,因为它通常保留在最高有效位中。例如,请尝试代码 Console.Write(-42 & 0xffffff);。或者我在这里漏掉了什么吗? - drharris
它只会保留最低的三个字节,这些字节是无符号的(因为你关于符号位在顶部字节的说法是正确的)。然而,即使使用掩码,42-42在进行AND操作后仍会产生不同的结果。 - Jeremiah Willcock
那么,我可以执行 int bit24 = bit32 & 0xffffff;,然后如果它测试为负数,就执行 bit24 |= 0x800000;?基本上是手动重置符号位吗? - drharris
你可以这样做:if (bit24 & 0x800000) bit32 = (bit24 | 0xFF000000); else bit32 = bit24; 来恢复符号位(因为在转换为32位时,所有高位都需要设置为保持值)。对于一个24位的数,符号位与32位数的位置不同。 - Jeremiah Willcock
2
我的错。我忽略了这些答案的十六进制实际内容。结果,在32位负数中,由于采用二进制补码(假设值确实限制在24位范围内),因此24位的正确位确实总是设置的。我已经测试了32位负数的全部范围,情况始终如此,所以简单地通过“0xffffff”屏蔽将始终有效。 - drharris

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接