I. Network byte order and host byte order
1. Big-endian and small-end storage
Big Endian: High-low address. Conform to the normal thinking of human beings. The network byte order uses the big-endian (the network transmits is the byte stream).
Small end (Littile Endian): Low save address.
If a 32-bit integer 0x12345678 is stored in an integer variable (int), this integer variable is stored in memory by the big-endian or small-end pattern, as shown in the following table.
---------------------------
Address offset big-endian mode small end mode
0x00 12 78
0X01 34 56
0X02 56 34
0X03 78 12
---------------------------
If a 16-bit integer 0x1234 is stored in a short integer variable (shorter). This short integer variable is stored in memory in the size end pattern as shown in the following table.
---------------------------
Address offset big-endian mode small end mode
0x00 12 34
0X01 34 12
---------------------------
Cases:
int main (int argc,char** argv)
{
int num = 0x12345678;
unsigned char* pc = (unsigned char*) (&num);
printf ("local order:\n");
printf ("[0]: 0x%X addr:%u\n", pc[0], &pc[0]);
printf ("[1]: 0x%X addr:%u\n", pc[1], &pc[1]);
printf ("[2]: 0x%X addr:%u\n", pc[2], &pc[2]);
printf ("[3]: 0x%X addr:%u\n", pc[3], &pc[3]);
num = htonl (num);
printf ("htonl order:\n");
printf ("[0]: 0x%X addr:%u\n", pc[0], &pc[0]);
printf ("[1]: 0x%X addr:%u\n", pc[1], &pc[1]);
printf ("[2]: 0x%X addr:%u\n", pc[2], &pc[2]);
printf ("[3]: 0x%X addr:%u\n", pc[3], &pc[3]);
return 0;
}
Output on the SPARC platform:
Local order:
[0]: 0x12 addr:4290770212//high-bit byte stored at the low address, it is the big-endian method;
[1]: 0x34 addr:4290770213
[2]: 0x56 addr:4290770214
[3]: 0x78 addr:4290770215//Low byte stored at the high address;
HTONL Order:
[0]: 0x12 addr:4290770212//This shows that the host byte sequence is the same as the network byte;
[1]: 0x34 addr:4290770213
[2]: 0x56 addr:4290770214
[3]: 0x78 addr:4290770215
Output on the X86 platform:
Local order:
[0]: 0x78 addr:4289157020//low-bit bytes stored at the low address, it is the small-end method;
[1]: 0x56 addr:4289157021
[2]: 0x34 addr:4289157022
[3]: 0x12 addr:4289157023//high-bit byte is stored at the higher address;
HTONL Order:
[0]: 0x12 addr:4289157020//This shows that the host byte sequence is not the same as the network byte;
[1]: 0x34 addr:4289157021
[2]: 0x56 addr:4289157022
[3]: 0x78 addr:4289157023
2. Does the byte-order conversion use htons () or htonl ()? or both?
First of all, these two functions are not used casually, single-byte data can not be converted, 2-byte data only use Htons () conversion, 4-byte data can only use HTONL ()
Reason: Example: for 2 short data 0x1234 and 0x5678, store the following
---------------------------
Address offset big-endian mode
0x00 12
0X01 34
0x02 56
0X03 78
If a long conversion function is used. If the sender is big-endian, then 0x1234 0x5678 use Htonl () to convert to network byte sequence, still 0x1234 0x5678;
If the receiving end is a small end, the two data exchange positions are changed after using Ntohl () conversion to 0x5678,0x1234.
---------------------------
Address offset small-end mode
0x00 78
0x01 56 Small End 0x5678
0X02 34
0x03 12 Small End 0x1234
---------------------------
So 2-byte and 4-byte conversions cannot be mixed. So the question comes, 8 bytes of double, how to convert?
Answer: If the current host is a small end, the first 4 bytes are converted using Ntohl () before receiving, then 4 bytes are converted using Ntohl () and then 4 bytes before and after the exchange.
When using the socket to transmit the data of class to the T_WFSTPMSG structure, the MSG part is difficult to transform because of the uncertain data type in the conversion, so it is necessary to define the data type of MSG and make it easy to convert. MSG is best to be a character.
Conversion is wrong, there will be a reverse of the problem.
3. The effect of byte alignment on the byte order
such as structural body
#pragma pack (4)
typedef struct {
Char A;
int b;
}am;
void Main (void)
{
AM a={1,2};
unsigned char *p= (unsigned char *) (&A);
int i=0;
while (I<8)
{
printf ("%4x", (INT) p[i]);
cout<<endl;
i++;
}
}
Print the structure data is saved as: (Big-endian)
1
Cc
Cc
Cc
2
0
0
0
HTONL (* (int *) (&a)) ==30198988==0X01CCCCCC!=1
So if you use the &am pointer, like MSG, with htonl () to convert, then it must be wrong. MSG affirms that the #pragma pack (1), which makes the data storage is compact, although it can circumvent the problem, but that no data type directly all use HTONL () conversion, there are some problems.
Two, byte alignment
How do I modify the compiler's default alignment values?
1. In the VC IDE, you can modify this: [project]| [settings],c/c++ tab category of the Code generation option of the struct Member alignment modified, the default is 8 bytes.
2. When encoding, you can modify this dynamically: #pragma pack (2). Note: It is pragma instead of progma.
The potential pitfalls of byte alignment: Many of the pitfalls of alignment in code are implicit. For example, when forcing type conversions. For example:
unsigned int i = 0x12345678;
unsigned char *p=null;
unsigned short *p1=null;
p=&i;
*p=0x00;
p1= (unsigned short *) (p+1); In some cups of the architecture, byte non-aligned access is not supported.
*p1=0x0000;
The last two lines of code, from the odd boundary to access the Unsignedshort variable, clearly do not conform to the rules of alignment.
On x86, similar operations can only affect efficiency, but on MIPS or SPARC, it can be an error because they require byte alignment.
How to find problems with byte alignment:
If an alignment or assignment problem occurs, first view
1. Compiler's big little side settings
2. See if the system itself supports non-aligned access
3. If supported, see whether the alignment is set or not, and if not, you need to add some special decorations to flag its special access operation.
Calculation of the number of storage units occupied by the struct (that is, the size calculated using sizeof)-
BYTE alignment: That is, where the address of each data type starts, and how many storage units are accounted for.
2 theorems: (Solve all problems)
Synchronization theorem: The structure itself and the effective alignment and maximum member synchronization
Integer multiples theorem: The initial memory address of a struct or ordinary data type is an integer multiple of a valid aligned byte, and the number of bytes in the struct or ordinary data type must be an integer multiple of its valid aligned bytes
1. First 3 alignment concepts in a struct:
Data type self-aligning: char 1,short 2,int 4,long 4,float 4,double 8 in 32-bit system
Data type Specifies alignment: The system specified with #pragma pack (x) uses X-byte alignment.
Valid data type alignment: The data type itself aligns with the number of valid aligned bytes in the specified alignment as the data type.
Synchronization theorem: The structure itself and the effective alignment and maximum member synchronization
2. Number of bytes of memory per data type calculation
#pragma pack (x)
Char: Start address (valid alignment) is 1 and smaller in X, accounting for 1 bytes
Short: Start address (valid alignment) is 2 and smaller in X, accounting for 2 bytes
int: The starting address (valid alignment) is 4 and the lesser of X, (if x=2, the address is in an integer multiple position of 2), accounting for 4 bytes
Double: The starting address (valid alignment) is 8 and the lesser of X, (if x=4, the address is in an integer multiple position of 4), accounting for 8 bytes
Integer multiples theorem: The initial memory address of a struct or ordinary data type is an integer multiple of a valid aligned byte, and the number of bytes in the struct or ordinary data type must be an integer multiple of its valid aligned bytes
3. Calculation of the number of bytes in the structure
Calculated in 3 steps:
(1) Calculate the memory space of each member separately (this is fixed for simple data type Int/char etc., but it needs to be calculated for the structure).
(2) with the initial address 0 as the coordinates, according to the effective alignment (starting address), and then place the individual members; calculates the memory length of the first member to the last member.
(3) According to the theorem (the number of bytes in a struct must be an integer multiple of its effective alignment byte), the memory length is the length of memory that is the last structure.
to struct a{int A;char b;short C;char D;}; Structural bodies For example #pragma pack (4)
1. The memory address and the occupied bytes of each member (the calculation is independent of the struct): int 0:4;char 4,1;short 6:2,char 8:1 total 9 address space
2. The effective alignment of the struct is the same as the valid alignment of the member with the largest self-aligning member: The largest of the members is 4, the specified alignment is 4, so the effective alignment is 4 (the lesser of the two), so the final structure of the memory space must be 4 integer times
3. So the structure of the number of bytes accounted for (9/4+1) *4=12, the above structure and struct a{int a;char b;short C;char d;char E;char f;}; The space occupied is the same.
Calculate the structure of a large hour answer 3 questions:
1. The members account for a few bytes
2. Where the starting address of each member starts (determined by the valid alignment value)
3. The space occupied by the structure is a number of multiples
struct a{//#pragma pack (4)
int A; 0:4
Char B;//4:1
Short C;//6:2
Char D;//8:1
int E;//12:4
The Char F://16:1 finally takes up 17 bytes, and the structure occupies a space of 4 integers, so the struct is 20 bytes
};
struct a{//#pragma pack (2)
int A; 0:4
Char B;//4:1
Short C;//6:2
Char D;//8:1
int E;//10:4
The Char F://14:1 finally takes up 15 bytes, and the structure occupies a space of 2 integers, so the struct is 16 bytes
};
struct a{//#pragma pack (1)
int A; 0:4
Char B;//4:1
Short C;//5:2
Char D;//7:1
int E;//8:4
The Char F://12:1 finally takes up 13 bytes, and the structure occupies a space of 1 integers, so the struct is 13 bytes
};
This article from "Tech record" blog, declined reprint!
BYTE-order aligned with byte