Address coercive type conversion in Go language

There are forced type conversions in other languages, but the way of expression is different, but the rules are the same, that is, small to large does not require forced conversion; while large to small requires forced type conversion; in fact, type conversion is plain It is used to convert a variable of one data type into a variable of another type.

Directly on the code:

struct Test
{
    
    
   int Num;
   char *pcName;
   short sDate;
   char cha[2];
   short sBa[4];
}*p;

Suppose the value of p is 0x100000. What are the values ​​of the expressions in the following table?

   p + 0x1 = 0x___ ?
   (unsigned long)p + 0x1 = 0x___?
   (unsigned int*)p + 0x1 = 0x___?

I believe that many people will not understand what this question means at first. In fact, let's take a closer look to see if this is a bit familiar. How to parse a pointer variable and an integer?

Remember the difference between our expression "a+1" and "&a+1" earlier? Actually it's the same here. Adding and subtracting a pointer variable to an integer is not directly adding or subtracting the integer with the address in the pointer variable. The unit of this integer is not byte but the number of elements.

So: the value of p + 0x1 is 0x100000+sizof(Test)*0x1. As for the size of this structure is 20byte, I won't go into details here. So the value of p +0x1 is: 0x100014.

What about the value of (unsigned long)p + 0x1? This involves coercion, coercing the value stored in the pointer variable p into an unsigned long integer. Once any value is coerced, its type is changed. So this expression is actually an unsigned long integer plus another integer. So its value is: 0x100001.

What about the value of (unsigned int*)p + 0x1? The p here is coerced into a pointer to an unsigned integer. So its value is: 0x100000+sizof(unsigned int)*0x1, which is equal to 0x100004.

Let’s talk about another example of forced type conversion:

intmain()
{
    
    
   int a[4]={
    
    1,2,3,4};
   int *ptr1=(int *)(&a+1);//指向a数组后面的内存单元,&a+1表示向后移16个存储单元
   int *ptr2=(int *)((int)a+1);//表示a的存储单元的地址增加一个字节
   printf("%x,%x",ptr1[-1],*ptr2);//ptr1[-1]其实指向的是a数组的最后一个单元,*ptr1则表示a数组的地址后移一个字节之后的4个连续存储单元所存储的值
   return 0;
}

Let's parse the meaning of this code:

ptr1 : Coercively convert the value of &a+1 to int type, and assign it to the variable ptr of type int , ptr1 must point to the next int type data of array a. ptr1[-1] is parsed as *(ptr1-1), that is, ptr1 goes back 4 bytes. So its value is 0x4.

ptr2 : According to the above explanation, the value of (int)a+1 is the address of the second byte of element a[0]. Then coerce this address to an int type value and assign it to ptr2, which means that the value of ptr2 should be the content of 4 consecutive bytes starting from the second byte of element a[0].

The detailed analysis is shown in the figure below:

Insert picture description here

So what exactly is stored in these 4 consecutive bytes? In other words, how are the values ​​in elements a[0] and a[1] stored?
This involves the large and small endian modes of the system, and I won't elaborate on the effect here. Since you don't know what mode the current system is, you have to find a way to test it.
We can use the following function to test the current system mode.

int checkSystem()

{
    
    

  union check

  {
    
    
      int i;
      char ch;

  } c;

  c.i = 1;

  return (c.ch ==1);//如果当前系统为大端模式这个函数返回0;如果为小端模式,函数返回1。

}

If the current system is in big-endian mode, this function returns 0;

If it is little-endian mode, the function returns 1.

That is to say, if the return value of this function is 1, the value of *ptr2 is 0x2000000. If the return value of this function is 0, the value of *ptr2 is 0x100.

Guess you like

Origin blog.csdn.net/zp17834994071/article/details/108745472