Preface
Generally, developers at the underlying layer have a lot of access to the concept of storage at the large and small ends, especially embedded developers. We know that no matter what type of operating system needs to access data or files, but the storage methods of each system vary depending on the CPU architecture. For all CPUs, there are two storage methods: Big-Endian and little-Endian ).
Common CPU architecture in byte order:
Big endian: PowerPC, IBM, sun
Little endian: x86, Dec
Definition:
A) Little-Endian isLow byte emissions are at the low address end of the memory, and high byte emissions are at the high address end of the memory..
B) Big-Endian isHigh byte emissions are at the low address end of the memory, and low byte emissions are at the high address end of the memory..
C) network byte sequence: TCP/IP Protocols define the byte sequence as big-Endian. Therefore, the byte sequence used in TCP/IP is usually called the network byte sequence.
Memory method:
The system stores data in bytes. Therefore, when processing data types larger than 1 byte, such as short and INT, there may be different storage locations. The Applied memory starts from the low level. Therefore, this method is determined or named based on the data stored in the low level. Therefore, the method of storing the high level data in the low level is called the Large-end byte sequence, low-level storage low-level storage is called the small-end byte sequence. Is this easy to remember?
As for the network byte sequence mentioned above, this concept comes from a term in network programming. In fact, it is a large-end byte sequence. Why is it not a large-end byte order, not a small-end byte order? I personally have such an understanding about this issue. As to whether or not I can judge it by myself, my understanding is as follows:
The destination address or source address during communication is the IP address we usually call. It is a four-byte numeric type (uint32_t ). assume that the IP address of a host is 192.68.1.1, the data bit from high to low is 192 68 1 1, and the system reads data from low to high. If the IP address is accessed in the byte order of the big end, the numbers from the low address to the high address are stored in sequence:, 68. In this way, the original IP address format can be formed when data is retrieved: 192 68 1, because the IP address needs to be in the form of these four numbers, it is also convenient to convert it into a string.
Storage example
The following table stores a 4-byte 0x12345678, which will not be shown in the drawing. The address is the corresponding table from top to bottom:
| Address |
Big-Endian |
Little-Endian |
| Zero x 0000 |
0x12 |
0x78 |
| Zero X 0004 |
0x34 |
0x56 |
| Zero X 0008 |
0x56 |
0x34 |
| Zero X 0012 |
0x78 |
0x12 |
Is the storage method of the size end clearer through the comparison in this table? How can we convert the size-end byte order? It's easy to switch the content in the high-end address to the content in the low-end address.
How to determine the byte storage sequence used by the CPU (size end)
The common method is the federated entity method. The Code is as follows:
1 bool isBigEndian() 2 { 3 union 4 { 5 int a; 6 char b; 7 }num; 8 9 num.a = 0x1234; 10 return ( num.b == 0x12 ) 11 }
Size end Conversion
I was asked this question during the interview. I wrote a macro to convert the size of a 16-bit server. I didn't write it at the time. I just replied: it is OK to switch the high and low addresses. Later, I thought about the fact that this problem is very simple. It is very easy to implement with the shift method, and it is highly efficient and fast.
The shift principle is relatively simple. It is equivalent to retaining the corresponding digits after the original data is moved. After the other positions are 0 and the content of each byte is ready, finally, the converted data is obtained after they are joined or joined.
1 // 16-bit Server 2 # DEFINE _ swp16 (A) (uint16) (a) & 0xff00)> 8) | \ 3 (uint16) (a) & 0x00ff) <8) 4 5 // 32-bit system, size side conversion 6 # DEFINE _ swp32 (A) (uint32) () & 0xff000000)> 24) | \ 7 (uint32) (a) & 0x00ff0000)> 8) | \ 8 (uint32) (a) & 0x0000ff00) <8) | \ 9 (uint32) (a) & 0x000000ff) <24 ))