C usage and the role of the union

In the preparation of C / C ++ program, when a plurality of elementary data types or complex data structures to be occupied at the same time a memory, we want to use the Commonwealth; when multiple types, multiple objects, whichever is the only thing more than a moment (we tentatively colloquially referred to as "n option 1"), we can also use the Commonwealth to play to their strengths.
First look at a piece of code:
union myun
{
  struct { int x; int y; int z; }u;
  int k;
}a;
int main()
{
  a.u.x =4;
  a.u.y =5;
  a.u.z =6;
  a.k = 0;
  printf("%d %d %d\n",a.u.x,a.u.y,a.u.z);
  return 0;
}

union type is shared memory, the maximum structural size as its size, in which case, Myun This structure contains u this structure, the size is also equal to u the size of this structure, laid out in memory for the order of declaration x, y, z from low to high, then the assignment of time, in memory, that is, the position x is placed 4, y position placed 5, z position placing 6, now k assignment, assignment of k because it is the union to share memory, the first address from the union began to be placed, the location is actually the beginning of the first address position x, so that the original location in memory of x k was replaced by the assigned value, it becomes 0, and this time to print, direct look at memory on the line, the location of which is the location x k is 0, without changing the value of the position of y, z, so it should be 0,5,6

When the program becomes:
union myun
{
  struct { int x; int y; int z; }u;
  int k;
  int j;
}a;
int main()
{
  a.u.x =4;
  a.u.y =5;
  a.u.z =6;
  a.k = 0;
  a.j = 1;
  printf("%d %d %d\n",a.u.x,a.u.y,a.u.z);
  return 0;
}

The result is 1,5,6 or covered from the lowest since the beginning of the address, rather than, as some people imagine is 0,1,6

 

Look at two questions:
Questions one: write a program to determine the system's CPU is Big endian or Little endian mode?
Analysis:
Little endian and Big endian order are two different CPU to store data. For integer, long integer data types, Big endian that first byte is the most significant byte (high byte of stored data in accordance with the low order address to a high to low byte address); and Little endian is Instead, it is considered the first byte is the least significant byte (according to low-bit byte of data from the high order to the low address to the address high byte).
For example, assume that the memory address 0x0000 and the following data:
0x12 0x34 0xAB 0xCD
if we go to a read address 0x0000 four-byte variable, if the byte order is big-endian, the readout result is 0x1234abcd; if a word sequence of bit little-endian, the readout result is 0xcdab3412. If we 0x1234abcd written to the memory to the beginning of 0x0000, then Little endian Big endian mode and store the results as follows:
address 0x0001 0x0002 0x0003 0x0000
Big-endian 0x12 0x34 0xAB 0xCD
Little-endian 0xCD 0xAB 0x34 0x12
In general, x86 series CPU is the little-endian byte order, PowerPC usually Big endian, as well as the CPU via jumpers to set the CPU operating in Little endian or Big endian mode.
answer:
Obviously, to answer this question is the only way a byte (CHAR / BYTE type) data and integer data is stored in a same memory starting address, by reading integer data, analysis CHAR / BYTE data Integer high or low data to determine the CPU work in Little endian or Big endian mode.
Draw the following answer:
typedef unsigned char BYTE;
int main(int argc, char* argv[])
{
  unsigned int num,*p;
  p = #
  num = 0;
  *(BYTE *)p = 0xff;
  if(num == 0xff)
  {
    printf("The endian of cpu is little\n");
  }
  else //num == 0xff000000
  {
    printf("The endian of cpu is big\n");
  }
  return 0;
}

In addition to the above method (cast pointer and integer data types through the first byte assignment, the assignment judge assigned to the high or low), there is no better way to do it?

We know that members of the union itself is stored in the same memory space (shared memory, it is the union to play a role in contributing to the place), so we can be a CHAR / BYTE data and an integer data at the same time as a union members, draw the following answer:

int checkCPU()
{
 {
 union w   {   
int a;   char b;   } c;   c.a = 1;   return (c.b == 1); } }

Return 1 are: Little endian, 0 represents: Big endian


Achieve the same function, let's look at the source code for the Linux operating system related to how it is done:
static union { char c[4]; unsigned long mylong; } endian_test = {{ 'l', '?', '?', 'b' } };

#define ENDIANNESS ((char)endian_test.mylong)

Linux 的内核作者们仅仅用一个union 变量和一个简单的宏定义就实现了一大段代码同样的功能!由以上一段代码我们可以深刻领会到Linux 源代码的精妙之处!(如果ENDIANNESS=’l’表示系统为little endian, 为’b’表示big endian )

 

试题二:假设网络节点A 和网络节点B 中的通信协议涉及四类报文,报文格式为“报文类型字段+报文内容的结构体”,四个报文内容的结构体类型分别为STRUCTTYPE1~ STRUCTTYPE4,请编写程序以最简单的方式组
织一个统一的报文数据结构。

分析:
报文的格式为“报文类型+报文内容的结构体”,在真实的通信中,每次只能发四类报文中的一种,我们可以将四类报文的结构体组织为一个union(共享一段内存,但每次有效的只是一种),然后和报文类型字段统一组织成一个报文数据结构。
解答:
根据上述分析,我们很自然地得出如下答案:
typedef unsigned char BYTE;
//报文内容联合体
typedef union tagPacketContent
{
  STRUCTTYPE1 pkt1;
  STRUCTTYPE2 pkt2;
  STRUCTTYPE3 pkt1;
  STRUCTTYPE4 pkt2;
}PacketContent;
//统一的报文数据结构
typedef struct tagPacket
{
  BYTE pktType;
  PacketContent pktContent;
}Packet;
本文为转载,出处已不详,感谢原作者!

转载于:https://www.cnblogs.com/dpflnevergiveup/p/3672679.html

Guess you like

Origin blog.csdn.net/weixin_34161029/article/details/94300703
Recommended