1. 程式人生 > >字節序的理解----C語言和Python語言

字節序的理解----C語言和Python語言

code n) name mes net oid unsigned import 應該

字節序是指多字節數據在計算機內存中存儲或者網絡傳輸時各字節的存儲順序。常見的主要有以下2種:

  • 小端序(Little-Endian):低位字節排放在內存的低地址端即該值的起始地址,高位字節排放在內存的高地址端。最符合人的思維的字節序,地址低位存儲值的低位,地址高位存儲值的高位。該序因為從人的第一觀感來說低位值小,就應該放在內存地址小的地方,也即內存地址低位,反之,高位值就應該放在內存地址大的地方,也即內存地址高位。在80X86平臺上,系統將多字節中的低位存儲在變量起始地址,使用小端法。
  • 大端序(Big-Endian):高位字節排放在內存的低地址端即該值的起始地址,低位字節排放在內存的高地址端。最直觀的字節序,地址低位存儲值的高位,地址高位存儲值的低位。該序不需考慮對應關系,只需要把內存地址從左到右按照由低到高的順序寫出把值按照通常的高位到低位的順序寫出,兩者對照,一個字節一個字節的填充進去。

常見的還一種是網絡序,即網絡字節順序,它是TCP/IP中規定好的一種數據表示格式,它與具體的CPU類型、操作系統等無關,從而可以保證數據在不同主機之間傳輸時能夠被正確解釋,網絡字節順序采用big endian排序方式。

在C語言中,為了進行轉換,socket庫中提供了轉換函數,包括下面四個:
  • htons:把unsigned short類型從主機序轉換到網絡序
  • htonl:把unsigned long類型從主機序轉換到網絡序
  • ntohs:把unsigned short類型從網絡序轉換到主機序
  • ntohl:把unsigned long類型從網絡序轉換到主機序
在使用little endian的系統中,這些函數會把字節序進行轉換;在使用big endian類型的系統中,這些函數會定義成空宏而不作任何轉換。 【例】如對於整數0x12345678,在Windows系統上(小端序存儲)使用C語言和Python語言查看其不同表示方式。 其位[0-31]表示方式為: 技術分享圖片
小端序(Little-Endian)和大端序(Big-Endian)的表示方式為: 技術分享圖片 其網絡字節序同大端法表示相同。 (1)C語言程序:
 1 #include <iostream>
 2 #include <WinSock.h>
 3 #pragma comment(lib, "ws2_32")
 4 using namespace std;
 5 
 6 void main()
 7 {
 8     int a = 0x12345678;
 9     cout<<"a = "<<showbase<<hex<<a<<endl;
10 cout<<"Little Endian: ["; 11 for (int i=0; i<4; i++) 12 { 13 cout<<int(*((char*)&a+i))<<" "; 14 } 15 cout<<"]"<<endl; 16 17 int b = htonl(a); 18 cout<<"Big Endian: ["; 19 for (int i=0; i<4; i++) 20 { 21 cout<<int(*((char*)&b+i))<<" "; 22 } 23 cout<<"]"<<endl; 24 25 getchar(); 26 }

其運行結果為:

技術分享圖片

在調試狀態下,在內存窗口中查看變量a和變量b的地址,也可以清晰的看到兩種字節序的不同存儲情況。本例中變量a和變量b的地址分別為0x00B3FD3C和0x00B3FD24:

技術分享圖片

(2)Python語言程序:

 1 # -*- coding: utf-8 -*-#
 2 
 3 #-------------------------------------------------------------------------------
 4 # Name:         LittleAndBigEndianTest
 5 # Description:  
 6 # Author:       Administrator
 7 # Date:         2018/7/8
 8 #-------------------------------------------------------------------------------
 9 
10 import sys
11 from struct import *
12 from ctypes import *
13 import numpy as np
14 
15 a = 0x12345678
16 print(a:  + hex(a))
17 for name, fmt in zip([LittleEndian: , BigEndian:    , Network:      ], [Struct(<1i), Struct(>1i), Struct(!1i)]):
18     buffer = create_string_buffer(fmt.size)
19     fmt.pack_into(buffer, 0, a)
20     data = np.frombuffer(buffer, dtype=np.uint8)
21     print(name + str(map(lambda x: hex(x), data)))

其運行結果為:

技術分享圖片

結果同C語言版本一致,同時也驗證了網絡字節序同大端序結果完全相同。

字節序的理解----C語言和Python語言