C language pointer type cast

 

              Quoting an article about C language pointer type casting:

In C language, any variable must occupy an address, and the 0-1 code in this address space is the value of this variable. Different data types occupy different sizes of space, but they all must have an address, and this address is the basis for hardware access, and the name is just a convenient way for programmers to remember this address. However, different variables have a 0-1 code in the machine, so we cannot determine the type of a value simply by examining its bits.

For example, the definition is as follows:

int a;

 float b;

double c;

 long double d;

(Assuming that the bytes they occupy are 4, 8, 8, and 10, and they are continuously stored in an address space, and the starting address is 100, then we can get the following memory distribution )

The a variable is composed of 0-1 codes in the 4-byte memory space starting at address 100 and ending at 103. The b variable consists of 0-1 codes in the 8-byte memory space starting at address 104 and ending at 112. In the machine, these memories are continuous 0-1 codes, the machine does not know that 100~103 are integers and 104~111 are floats, all these types are told by the compiler. When we use a, since we previously defined a as int, the compiler knows to fetch 4 bytes backward from the address of a and then interpret it as int. Then (float)a is to first take out the value according to the int type, and then convert the value to the float type according to the rules of int to float. Therefore, forced type conversion is to take out the value of a variable according to the type of a variable, and then perform forced conversion according to the rules of ***to***. If it is a (type name) constant, the constant is cast according to the rules of the constant to type.

The pointer is also a variable, which occupies a 4-byte address space by itself (since the addressing space of the program is 2^32 power, that is, 4GB, so using 4 bytes to represent the pointer can already point to any program that can address The size of the pointer is 4 bytes), and its value is the address of another thing, which can be a normal variable, a structure, a function, and so on. Since the size of the pointer is 4 bytes, we can cast the pointer to int or other types. Similarly, we can also convert any constant to int and assign it to the pointer. The space occupied by all pointers is 4 bytes. They are only of different declared types. Their values ​​are all addresses that point to something. They have no essential difference to the machine. Coercion can be performed between them.
The type conversion of pointer to pointer refers to converting the type of the content pointed to by the pointer from the original type to the latter type.

 

int a = 1;

int *p = &a;

float *p1 = (float*)p;

The values ​​of p and p1 are both &a, but *p interprets the value in the address of &a as an int variable, while *p1 interprets the value in the address of &a as a float variable.

 

 

In view of the need for such flexible casts between pointers and to simplify the code, ANSI C introduced the null pointer or void*. The void pointer is also known as the universal pointer. In many programs today, when the parameters are uncertain, the universal pointer is used instead. This type of pointer is particularly common in thread\process functions.

ANSI C stipulates that a void pointer can be copied to a pointer of any other type, and a pointer of any other type can also be copied to a void pointer, and there is no need for type conversion between them. Of course any address can also be copied to a void pointer. We often see statements such as accept(socket, (struct sockaddr *)&saddr_c, &lenth) in "Network Programming". The code (struct sockaddr *) needs to be added before &saddr_c because when this function was designed, ANSI C The concept of void* has not been proposed yet . All addresses are identified by the struct sockaddr type, and the second parameter of this function is also a pointer to the struct sockaddr type, which is a forced type conversion here.

Of course, pointers of different types can also be directly assigned in some compilers, but in general a type mismatch warning will be given. Requiring the programmer to explicitly give a pointer cast can remind the programmer to use pointers with care, and has certain advantages for clarifying the purpose of the program.

1. Pointer type coercion:

int m;

int *pm = &m;

char *cp = (char *)&m;

pm points to an integer, cp points to the first byte of the integer

 

2. Coercion between structures

struct str1 a;

 

struct str2 b;

a=(struct str1) b;                  //this is wrong

a=*((struct str1*)&b);         //this is correct

 

 

3. Explanation of a program

 

 

int main(void)

{

    int a[4] = {1, 2, 3, 4};

    int *ptr1=(int *)(&a+1);

    int *ptr2=(int *)((int)a+1);

    int *c = *(a + 1);

    printf("%x, %x,%x\n", ptr1[-1], *ptr2,*c);

    return 0;

}

The output is 4 and 2000000,2 respectively

 

The formula &a+1 represents pointer addition, not ordinary numerical addition.

Under vs2008, where a = 0x001bfc18
(&a + 1) = 0x001bfc28
and a+1 = 0x001bfc1c

 The value of &a + 1 depends on the type of a if a declares int a;
then &a + 1 = 0xFFFF5704 = a + 1
if int a(ArryLen);
then &a + 1 = 0xFFFF5700 + 4 * ArryLen <> a + 1

a represents the starting address of the array, (int) a represents converting the address of a to an integer, (int) a + 1 represents ordinary numerical addition, (int *) ((int) a + 1) represents the (int) a + 1 is converted to the address of an integer pointer. This address points to the first byte of the array a(0) (counting from 0), because it is of type int, it needs four bytes of interpretation, so the result is the last three bytes of a(0) and a( 1) A value consisting of the first byte, which is endian-independent.

 *(a + 1) At this time, a is already a constant pointer. This expression calculates the address of the second element after the element pointed to by a, and then dereferences it to get the corresponding value. This expression is equivalent to

int last = a[1]

 

Paste the following code:

copy code
#include <stdio.h>

typedef struct stu1{
    char chs[5];
};
typedef struct stu2{
    char chs[4];
    int  n;
};

int main(int argc, char const *argv[]){
    struct stu1 s1;
    struct stu2 s2;
    s1.chs[0] = 'a';
    s1.chs[1] = 'b';
    s1.chs[2] = 'c';
    s1.chs[3] = 'd';
    s1.chs[4] = 'e';
    s2 = *((struct stu2 *)&s1);
    printf("%c\n", s1.chs[3]);
    printf("%d\n", s2.n);
    return 0;
}
copy code

Result output:

1 d
2 101

All types are essentially the same at the bottom of the system, and they are composed of 0 and 1 in memory. The basic type conversion is to truncate the higher part of the bit. When an int-type value is assigned to a char-type variable, only the lowest 8 bits are retained, and the high-order part is discarded

 

Looking at a piece of code:

copy code
1 #include <stdio.h>
 2
 3
 4 typedef struct stu1{
 5     int m;
 6     int n;
 7 };
 8 typedef struct stu2{
 9     char c1;
10     char c2;
11 };
12 int main(int argc, char const *argv[]){
13     struct stu1 s1;
14     struct stu2 s2;
15     s1.m = 815;  //11 00101111
16     s1.n = 600;  
17     s2 = *((struct stu2 *)&s1);
18     printf("%d, %d, \n", s2.c1, s2.c2);
19     int a = 559; //10 00101111
20     char c = (char)a;
21     printf("%d\n", c);
22     s1.m = 559;
23     s2 = *((struct stu2 *)&s1);
24     printf("%d, %d, \n", s2.c1, s2.c2);
25     return 0;
26 }
copy code

Output result:

47, 3,
47
47, 2,

The size of the stu1 structure in the above code is 4 bytes, and the size of the stu2 structure is 2 bytes, so when stu1 is converted to stu2, only the first 2 bytes are reserved. s1.m is of int type and s2.ch1 is of char type. As mentioned earlier, when an int type value is assigned to a char type variable, only the lowest 8 bits are reserved, and the high bits are discarded

We can see that the last (low) eight bits (one byte) of 815 and 559 are the same 47. The remaining one byte (the high eight bits of s1.m) is assigned to the high eight bits of s2.ch2 815 and 559, so the output results are different.  

The coercion between pointers in C language is the coercion between the contents pointed to by their pointers. A byte A conversion between bytes. Cut off the extra part.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325215292&siteId=291194637