【发布时间】:2015-03-16 12:48:37
【问题描述】:
我有一个寄存器,可以按照以下格式读出版本号。它是小端。例如:
读取的寄存器值为0x15000000,但我需要在GUI 中将其表示为00.00.00_15。
如何在 C# 中处理反转并以特定格式打印?
【问题讨论】:
-
你从哪里读取这个值?
标签: c#
我有一个寄存器,可以按照以下格式读出版本号。它是小端。例如:
读取的寄存器值为0x15000000,但我需要在GUI 中将其表示为00.00.00_15。
如何在 C# 中处理反转并以特定格式打印?
【问题讨论】:
标签: c#
您可以使用BitConverter.GetBytes 来获取字节数组..
int num = 0x15000000;
var bytes = BitConverter.GetBytes(num);
// If you want your code to run even on your Big Endian fridge,
// decomment this line :)
// if (!BitConverter.IsLittleEndian) Array.Reverse(bytes);
string str = string.Format("{0:x2}.{1:x2}.{2:x2}_{3:x2}", bytes[0], bytes[1], bytes[2], bytes[3]);
然后是 string.Format("{num:x2}",其中 x2 将给出 2 位的十六进制格式
请注意,一般情况下,BitConverter.GetBytes 只能在 Intel/AMD 计算机上使用!如果你想制作一个可以在任何地方运行的通用代码,包括你的冰箱,那么最好使用下一个解决方案! (因为你的冰箱可能是大端!)
显然你可以进行位操作,移位>> 和&
string str = string.Format("{0:x2}.{1:x2}.{2:x2}_{3:x2}", num & 0xFF, (num >> 8) & 0xFF, (num >> 16) & 0xFF, (num >> 24) & 0xFF);
但它非常不可读,除非你知道一点位操作:)
【讨论】:
IsLittleEndianstatic。
不要把它当作一个数字——它不是一个数字。您可以有效地将其存储为单个 int 的事实无关紧要 - 只是一个实现细节。
一旦你开始考虑数组中的字节,你会发现“小端”实际上并不重要。相反,你只是有一个结构,以一个字节开始,表示一件事,下一个字节表示另一件事......
有很多方法可以实现这种行为,具体取决于您获得实际值的位置 - 例如,采用 int 不会让您控制字节顺序。如果你只是拿一个byte[],你可以这样做:
string.Format("{0}.{1}.{2}_{3}", data[3], data[2], data[1], data[0])
这通常在您使用时很容易处理,例如从文件加载数据,或通过套接字发送数据。如果您正在处理本机代码互操作,则可以使用结构而不是 int(或类似的):
struct MyVersionNumber
{
byte Lowest;
byte Other;
byte YetAnother;
byte Highest;
}
考虑类型 - 不要使用原始值,除非您拥有的是原始值。您显然正在使用(无论出于何种原因)折叠成原始类型的复合值。这不是保持复杂性的好主意:)
一旦你有了类型,你就可以确保正确的类型安全和验证,并且只需覆盖ToString 方法,例如,为用户输出值。
【讨论】:
大部分但不是全部.net platforms are little endian。因此,BitConverter.GetBytes 的正确用法是不要假设它会返回一个或另一个。
int num = 0x15000000;
var bytes = BitConverter.GetBytes(num);
if (!BitConverter.IsLittleEndian) Array.Reverse(bytes); //it's big-endian, so reverse the bytes
string str = string.Format("{0:x2}.{1:x2}.{2:x2}_{3:x2}", bytes[0], bytes[1], bytes[2], bytes[3]);
【讨论】: