我最近被分配到一个C ++项目,涉及通过UDP在计算机之间发送的信息。当数据包到达时,我有一个程序接受数据并可以将其显示为原始十六进制字符串。但是,我正在努力准确地掌握整个过程应该如何工作。十六进制字符串应该包含几个字段(例如一个4字符数组,一些float_32s和一些uint_32s)。
如何将此字符串的各个部分翻译成正确的变量类型?第一个值,一个ASCII标题,很简单;十六进制字符串中的前八个字符是ASCII字的十六进制表示(0x45十六进制可以直接转换为大写字母E)。但是下一个值,一个32位浮点数,对我来说并没有多大意义。十六进制值“42 01 33 33”与浮点值“32.3”(给定示例)之间的关系是什么?
我在这里有点头脑,我觉得我遗漏了一些有关数字系统工作方式的重要信息。
答案 0 :(得分:2)
C中的所有类型都有一个表示(大多数类型由特定实现定义)。大多数C实现使用IEEE 754来表示浮动类型(这实际上可能是C和C ++的要求,但是从内存中它不是)。 Wikipedia文章解释了浮动类型如何在内存中表示。在大多数C和C ++实现中,float
是32位类型,double
是64位类型。因此,在这些实现中,float
宽度为4个字节,double
宽度为8个字节。
要小心,因为字节顺序可能不同。一些架构以小端存储浮动类型,一些以大端存储。还有关于endianness的维基百科文章。
要将字节复制到浮动类型,您必须确保浮动类型与您拥有的字节数相同,然后您可以将字节逐个“复制”到浮动中类型。这样的东西会给你一个要点:
unsigned char rep[] = { 0x42, 0x01, 0x33, 0x33 };
float someFloat;
if (sizeof(someFloat) == 4)
{
memcpy(&someFloat, rep, sizeof(someFloat));
}
else
{
// throw an exception or something
}
还有其他方法可以将字节复制到浮动类型,但要注意“违反规则”(类型惩罚等)。此外,如果结果值不正确,可能是因为字节顺序错误,因此您需要反向复制字节,以便表示中的第4个字节是浮点数的第1个字节。
答案 1 :(得分:1)
如果您有十六进制值:
42 01 33 33
相当于
0100 0010 0000 0001 0011 0011 0011 0011
二进制代码。
现在,有一个名为IEEE 754的浮点标准,它告诉您如何将浮点数格式化为二进制或后面。
它的要点是第一位是符号(正数/负数),接下来的8位是指数,最后23位是mantisse。这是计算机内部保存浮点数的方式,因为它只能存储1和0。
如果按照IEEE指定的方式将它们全部加在一起,则得到32.3。
答案 2 :(得分:0)
确切的数据格式由所使用的协议指定,但表示数字数据的常用方法是:
无符号整数:这实际上是最简单的。它的典型表示原则上就像普通的十进制系统一样,除了“数字”是字节,并且可以有256个不同的值。
如果您查看像3127这样的十进制数字,您会看到三位数字。最低有效位是最后一位(在本例中为7)。最不重要意味着如果将其更改为1,则会得到值的最小变化(即1)。示例中最重要的数字是最左侧的3:如果您将该值更改为1,则进行值的最大更改,即更改1000.由于有10个不同的数字(0到9),由“3127”表示的数字是3 * 10 * 10 * 10 + 1 * 10 * 10 + 2 * 10 + 7.注意itz只是最重要的数字首先出现的惯例;你也可以定义最低有效数字首先出现,然后这个数字写成“7213”。
现在在大多数编码中,无符号数的作用完全相同,只是“数字”是字节,因此我们将基数为256而不是基数10.此外,与十进制数字不同,没有普遍的约定是否最重要首先是字节(MSB)或最低有效字节(LSB);这两种约定都以不同的协议或文件格式使用。
例如,在4字节(即32位)unsigned int中,MSB优先(也称为big-endian编码),值1000 = 0 * 256 ^ 3 + 0 * 256 ^ 2 + 3 * 256 + 232将由四个字节值0, 0, 3, 232
或十六进制00 00 03 E8
表示。对于little-endian编码(LSB优先),它将是E8 03 00 00
。并且作为16位整数,它只是03 E8
(大端)或E8 03
(小端)。
对于有符号整数,最常用的表示是两个补码。基本上它意味着如果最高有效位为1(即最高有效字节为128或更大),则字节序列不对上面写的数字进行编码,而是通过减去2 ^(位)得到的负数从中,其中(位)是数字中的位数。例如,在带符号的16位int中,序列FF FF
不是65535,而是16位无符号int,而是65535-2 ^ 16 = -1。与无符号整数一样,您必须区分big-endian和little-endian。例如,-3在16位bit endian中为FF FD
,在16位little endian中为FD FF
。
浮点要复杂得多;今天通常使用IEEE / IEC规定的格式。基本上,浮点数的形式为符号*(1.mantissa)* 2 ^指数,符号,尾数和指数存储在不同的子字段中。同样,还有little-endian和big-endian形式。