2012-01-10 34 views
1

我最近被分配到一個C++項目,涉及通過UDP在計算機之間發送的信息。當數據包到達時,我有一個接受數據的程序,並可以將它顯示爲原始十六進制字符串。然而,我正在努力掌握整個過程應該如何工作。據推測,十六進制字符串包含多個字段(例如,一個4字符數組,一些float_32s和一些uint_32s)。搞清楚網絡,十六進制和ascii如何交互

如何將該字符串的部分轉換爲正確的變量類型?第一個值,一個ASCII標題,很簡單,十六進制字符串中的前八個字符是ASCII字的十六進制表示(十六進制可以直接翻譯爲大寫字母E)。但是下一個值,一個32位浮點數,對我來說並沒有什麼意義。十六進制值「42 01 33 33」和浮點值「32.3」(給出的例子)之間的關係是什麼?

我在這裏有點累贅,我覺得我錯過了關於數字系統工作方式的一些重要信息。

+2

「十六進制字符串」只是「原始」。相反,它是原始二進制數據的十六進制*表示*。閱讀[float format](http://en.wikipedia.org/wiki/Single-precision_floating-point_format)瞭解它如何適合四個字節。 – 2012-01-10 22:33:20

回答

2

C中的所有類型都有一個表示(對於大多數類型來說,它是由特定的實現定義的)。大多數C實現使用IEEE 754來表示浮點類型(這實際上可能是C和C++的一個需求,但是從內存中它不是)。維基百科文章解釋瞭如何在內存中表示浮點類型。在大多數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個字節。

+0

這段代碼給了我奇怪的結果;根據我的調試器,'someFloat'的值爲4.1667829e-008,當我嘗試使用myStr.Format(「%f」,someFloat)將其粘貼到CString中時,它始終打印爲「0.000000」。 – Andrew 2012-01-11 19:19:56

+0

AHA!我需要仔細閱讀,正如你所建議的那樣,問題在於字節順序錯誤。我使用了{0x33,0x33,0x01,0x42}並得到了32.299999!謝謝! – Andrew 2012-01-11 19:35:29

1

如果你有一個十六進制值:

42 01 33 33 

這是

0100 0010 0000 0001 0011 0011 0011 0011 

二進制代碼的等價物。

現在有一個名爲IEEE 754的浮點標準,它告訴你如何將浮點數格式化爲二進制或後面的格式。

它的要點是第一位是符號(正數/負數),接下來的8位是指數,最後23位是mantisse。這是計算機內部保存浮點數的方式,因爲它只能存儲1和0。

如果以IEEE指定的方式將它們加在一起,則得到32.3。

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」。

現在在大多數編碼中,無符號數字的工作原理完全相同,除了「數字」是字節,因此而不是基數爲10的基數爲256.此外,與十進制數不同,重要字節(MSB)或最低有效字節(LSB)首先出現;兩種約定都以不同的協議或文件格式使用。例如,在MSB優先(也稱爲big-endian編碼)的4字節(即32位)無符號整數中,值1000 = 0 * 256^3 + 0 * 256^2 + 3 * 256 + 232將由四個字節值0, 0, 3, 232或十六進制00 00 03 E8表示。對於little-endian編碼(首先是LSB),代之以。而作爲16位整數,它只是03 E8(大端)或E8 03(小端)。

對於有符號整數,最常用的表示形式是二進制補碼。基本上這意味着如果最高有效位是1(即最高有效字節是128或更大),則字節序列不會像上面所寫的那樣對數字進行編碼,而是通過減去2 ^(位)從它開始,其中(位)是數字中的位數。例如,在一個有符號的16位int中,序列FF FF不是65535,因爲它將在16位無符號整型中,而是65535-2^16 = -1。與未簽名的整數一樣,您必須區分大端和小端。例如,-3將是16位位端的FF FD,而16位的小端是FD FF

浮點比較複雜一點,今天通常使用IEEE/IEC規定的格式。基本上,浮點數的形式是符號*(1.mantissa)* 2 ^指數,符號,尾數和指數存儲在不同的子域中。再次,有小端和大端形式。