C language pointer explanation

Preface: Complex Type Specifications

To understand pointers, more or less complex types will appear, so let me first introduce how to fully understand a complex type. It is actually very simple to understand a complex type. There will be many operators in a type. They also have priorities like ordinary expressions. Their priority is the same as that of operations. So I summarized the principle: starting from the variable name, combined with operator priority, and analyzing step by step. Let’s start with the simple type and slowly analyze it:

1. int p; //这是一个普通的整型变量 

2. int *p; //首先从P 处开始,先与*结合,所以说明P 是一个指针,
            //然后再与int 结合,说明指针所指向的内容的类型为int 型.
            //所以P是一个返回整型数据的指针 

3. int p[3]; //首先从P 处开始,先与[]结合,说明P 是一个数组
            //然后与int 结合,说明数组里的元素是整型的,所以P 是一个由整型数据组成的数组 

4. int* p[3]; //首先从P 处开始,先与[]结合,因为其优先级比*高,//指针的数组
                //所以P 是一个数组,然后再与*结合,说明数组里的元素是指针类型
                //然后再与int 结合,说明指针所指向的内容的类型是整型的
                //所以P 是一个由返回整型数据的指针所组成的数组 

5. int (*p)[3]; //首先从P 处开始,先与*结合,//数组的指针
                //说明P 是一个指针然后再与[]结合(与"()"这步可以忽略,只是为了改变优先级),说明指针所指向的内容是一个数组,然后再与int 结合,说明数组里的元素是整型的.所以P 是一个指向由整型数据组成的数组的指针 
 
6. int **p; //首先从P 开始,先与*结合,说是P 是一个指针,然后再与*结合,
            //说明指针所指向的元素是指针,然后再与int 结合,说明该指针所指向的元素是整型数据.
            //由于二级指针以及更高级的指针极少用在复杂的类型中,
            //所以后面更复杂的类型我们就不考虑多级指针了,最多只考虑一级指针. 

7. int p(int); //从P 处起,先与()结合,说明P 是一个函数
                //然后进入()里分析,说明该函数有一个整型变量的参数
                //然后再与外面的int 结合,说明函数的返回值是一个整型数据 

//8的指针是指向函数的指针
8. int (*p)(int); //从P 处开始,先与指针结合,说明P 是一个指针
                    //然后与()结合,说明指针指向的是一个函数,然后再与()里的int 结合
                    //说明函数有一个int 型的参数,再与最外层的int 结合
                    //说明函数的返回类型是整型
                    //所以P 是一个指向有一个整型参数且返回类型为整型的函数的指针 
   int* p() //P代表的是返回是指针,而且指针指向的类型是int
9. int *(*p(int))[3]; //可以先跳过,不看这个类型,过于复杂从P 开始,先与()结合
                         //说明P 是一个函数,然后进入()里面,与int 结合
                    //说明函数有一个整型变量参数,然后再与外面的*结合
                    //说明函数返回的是一个指针,,然后到最外面一层,先与[]结合
                    //说明返回的指针指向的是一个数组,然后再与*结合
                    //说明数组里的元素是指针,然后再与int 结合
                    //说明指针指向的内容是整型数据
       //所以P 是一个参数为一个整数据且返回一个指向由整型指针变量组成的数组的指针变量的函数.

That’s about it, and we have so many tasks. After understanding these types, other types are also a piece of cake for us, but we generally don’t use too complicated types, which will greatly reduce the readability of the program. Please use them with caution. The above types are enough for us.

1. Elaborate pointers

A pointer is a special variable whose value is interpreted as an address in memory. To figure out a pointer, you need to figure out four aspects of the pointer: the type of the pointer, the type pointed to by the pointer, the value of the pointer or the memory area pointed to by the pointer, and the memory area occupied by the pointer itself. Let's break it down separately.

Declare a few pointers as an example:

Example 1:

(1)int*ptr; 
(2)char*ptr; 
(3)int**ptr; 
(4)int(*ptr)[3]; 
(5)int*(*ptr)[4];

1. The type of pointer

From a grammatical point of view, you only need to remove the pointer name in the pointer declaration statement, and the rest is the type of the pointer. This is the type the pointer itself has. Let's look at the types of each pointer in Example 1:

(1)int*ptr;//指针的类型是int*
(2)char*ptr;//指针的类型是char*
(3)int**ptr;//指针的类型是int**
(4)int(*ptr)[3];//指针的类型是int(*)[3]
(5)int*(*ptr)[4];//指针的类型是int*(*)[4]

How about it? Isn't there a simple way to find out the type of a pointer?

2. The type pointed to by the pointer

When you use a pointer to access the memory area pointed to by the pointer, the type pointed to by the pointer determines what the compiler will treat the contents of that memory area as.

From a grammatical point of view, you only need to remove the pointer name in the pointer declaration statement and the pointer declarator * on the left of the name, and the rest is the type pointed to by the pointer. For example:

(1)int*ptr; //指针所指向的类型是int
(2)char*ptr; //指针所指向的的类型是char
(3)int**ptr; //指针所指向的的类型是int*
(4)int(*ptr)[3]; //指针所指向的的类型是int()[3]
(5)int*(*ptr)[4]; //指针所指向的的类型是int*()[4] 

In pointer arithmetic, the type pointed to by the pointer plays a big role.

The type of the pointer (that is, the type of the pointer itself) and the type pointed to by the pointer are two concepts. When you become more and more familiar with C, you will find that dividing the concept of "type" mixed with pointers into two concepts of "type of pointer" and "type pointed to by pointer" is one of the key points to master pointers. I read a lot of books, and found that some poorly written books mixed the two concepts of pointers together, so the books seemed inconsistent, and the more I read, the more confused I became.

3. The value of the pointer----or the memory area or address pointed to by the pointer

The value of the pointer is the value stored in the pointer itself, and this value will be treated by the compiler as an address, not a general value. In 32-bit programs, the value of all types of pointers is a 32-bit integer, because all memory addresses in 32-bit programs are 32-bit long. The memory area pointed to by the pointer starts from the memory address represented by the value of the pointer and has a length of size zeof (the type pointed to by the pointer). In the future, when we say that the value of a pointer is XX, it is equivalent to saying that the pointer points to a memory area whose address is headed by XX; when we say that a pointer points to a certain memory area, it is equivalent to saying that the value of the pointer is the first address of this memory area. The memory area pointed to by the pointer and the type pointed to by the pointer are two completely different concepts. In Example 1, the type pointed to by the pointer already exists, but since the pointer has not been initialized, the memory area pointed to by it does not exist, or is meaningless.

In the future, whenever you encounter a pointer, you should ask: What is the type of this pointer? What type does the pointer point to? Where does this pointer point to? (key note)

4 The memory area occupied by the pointer itself

How much memory does the pointer itself occupy? You only need to use the function sizeof (pointer type) to measure it. On 32-bit platforms, the pointer itself occupies 4 bytes in length. The concept of the memory occupied by the pointer itself is useful in determining whether a pointer expression (explained later) is an lvalue.

2. Arithmetic operations on pointers

A pointer can be plus or minus an integer. The meaning of this operation of the pointer is different from the meaning of the addition and subtraction of the usual value, and the unit is the unit. For example:

Example 2:

1.     char a[20]; 
2.     int *ptr=(int *)a; //强制类型转换并不会改变a 的类型 
3.     ptr++; 

In the above example, the type of the pointer ptr is int*, the type it points to is int, and it is initialized to point to the integer variable a. In the next third sentence, the pointer ptr is added by 1, and the compiler handles it like this: it adds sizeof(int) to the value of the pointer ptr, and in a 32-bit program, 4 is added, because in a 32-bit program, int occupies 4 bytes. Since the address is in bytes, the address pointed to by ptr increases by 4 bytes from the original address of variable a to the high address direction. Since the length of the char type is one byte, ptr originally pointed to the four bytes starting from the 0th unit of the array a, and now it points to the four bytes starting from the 4th unit in the array a. We can iterate over an array with a pointer and a loop, see example:

Example three:

int array[20]={0}; 
int *ptr=array; 
for(i=0;i<20;i++) 
{ 
    (*ptr)++; 
      ptr++; 
} 

This example adds 1 to the value of each cell in an integer array. Since the pointer ptr is incremented by 1 unit each time, the next unit of the array can be accessed each time.

Look at the example again:

Example four:

1. char a[20]="You_are_a_girl"; 
2. int *ptr=(int *)a; 
3. ptr+=5;

In this example, 5 is added to ptr, and the compiler handles it like this: add 5 times sizeof(int) to the value of the pointer ptr, and add 5 times 4=20 in a 32-bit program. Since the unit of the address is byte, the address pointed to by the current ptr has moved 20 bytes to the higher address direction than the address pointed to by the ptr after adding 5.

In this example, ptr before adding 5 points to the four bytes starting from the 0th unit of array a, after adding 5, ptr has already pointed to outside the legal range of array a. Although this situation is problematic in application, it is grammatically OK. This also reflects the flexibility of the pointer. If in the above example, ptr is subtracted by 5, then the process is similar, except that the value of ptr is subtracted by 5 times sizeof(int), and the address pointed to by the new ptr will move 20 bytes lower than the address pointed to by the original ptr.

Allow me to give another example below: (a misunderstanding)

Example five:

1.     #include<stdio.h> 
2.     int main() 
3.     { 
4.         char a[20]=" You_are_a_girl"; 
5.         char *p=a; 
6.         char **ptr=&p; 
7.         //printf("p=%d\n",p); 
8.         //printf("ptr=%d\n",ptr); 
9.         //printf("*ptr=%d\n",*ptr); 
10.         printf("**ptr=%c\n",**ptr); 
11.         ptr++; 
12.         //printf("ptr=%d\n",ptr); 
13.         //printf("*ptr=%d\n",*ptr); 
14.         printf("**ptr=%c\n",**ptr); 
15.     }  

Misunderstanding 1, the output answer is Y and o

Misunderstanding: ptr is a secondary pointer of char. When ptr++; is executed, a sizeof(char) will be added to the pointer, so the above result is output. This may only be the result of a small number of people.

Misunderstanding 2. The output answer is Y and a misunderstanding: ptr points to a char * type. When ptr++; is executed, a sizeof(char *) will be added to the pointer (some people may think that this value is 1, and then they will get the answer to Misunderstanding 1. This value should be 4, refer to the previous content), that is, &p+4; Doesn’t a value operation point to the fifth element in the array? Isn’t the output result the fifth element in the array? The answer is no.

Positive solution: The type of ptr is char **, the pointed type is a char * type, and the pointed address is the address of p (&p). When ptr++; is executed, a sizeof(char*) will be added to the pointer, that is, &p+4; Where does *(&p+4) point? You can ask God, or he will tell you where it is? So the final output will be a random value, perhaps an illegal operation.

in conclusion:

After adding (subtracting) an integer n to a pointer ptrold, the result is a new pointer ptrnew. The type of ptrnew is the same as that of ptrold, and the type pointed to by ptrnew is also the same as the type pointed to by ptrold. The value of ptrnew will be increased (decreased) by n times sizeof(the type pointed to by ptrold) bytes from the value of ptrold. That is to say, the memory area pointed to by ptrnew will move n times sizeof (the type pointed to by ptrold) bytes to the higher (lower) address direction than the memory area pointed to by ptrold. Addition and subtraction of pointers and pointers: two pointers cannot be added, which is an illegal operation, because after the addition, the result points to an unknown place and is meaningless. Two pointers can be subtracted, but they must be of the same type, which is generally used in arrays, so I won't say much.

3. Operators & and *

Here & is the address operator and * is the indirection operator.

The operation result of &a is a pointer, the type of the pointer is the type of a plus *, the type pointed to by the pointer is the type of a, and the address pointed to by the pointer is the address of a.

The operation results of *p are varied. In short, the result of *p is the thing pointed by p, and this thing has these characteristics: its type is the type pointed to by p, and the address it occupies is the address pointed to by p.

Example six:

1. int a=12; int b; int *p; int **ptr; 
2. p=&a; //&a 的结果是一个指针,类型是int*,指向的类型是 
3. //int,指向的地址是a 的地址。 
4. *p=24; //*p 的结果,在这里它的类型是int,它所占用的地址是 
5. //p 所指向的地址,显然,*p 就是变量a。 
6. ptr=&p; //&p 的结果是个指针,该指针的类型是p 的类型加个*, 
7. //在这里是int **。该指针所指向的类型是p 的类型,这 
8. //里是int*。该指针所指向的地址就是指针p 自己的地址。 
9. *ptr=&b; //*ptr 是个指针,&b 的结果也是个指针,且这两个指针 
10. //的类型和所指向的类型是一样的,所以用&b 来给*ptr 赋 
11. //值就是毫无问题的了。 
12. **ptr=34; //*ptr 的结果是ptr 所指向的东西,在这里是一个指针, 
13. //对这个指针再做一次*运算,结果是一个int 类型的变量。

4. Pointer expressions

If the result of an expression is a pointer, then the expression is called a pointer expression.

Here are some examples of pointer expressions:

Example 7:

1. int a,b; 
2. int array[10]; 
3. int *pa; 
4. pa=&a; //&a 是一个指针表达式。 
5. Int **ptr=&pa; //&pa 也是一个指针表达式。 
6. *ptr=&b; //*ptr 和&b 都是指针表达式。 
7. pa=array; 
8. pa++; //这也是指针表达式。

Example eight:

1. char *arr[20]; 
2. char **parr=arr; //如果把arr 看作指针的话,arr 也是指针表达式 
3. char *str; 
4. str=*parr; //*parr 是指针表达式 
5. str=*(parr+1); //*(parr+1)是指针表达式 
6. str=*(parr+2); //*(parr+2)是指针表达式

Since the result of a pointer expression is a pointer, the pointer expression also has four elements that a pointer has: the type of the pointer, the type pointed to by the pointer, the memory area pointed to by the pointer, and the memory occupied by the pointer itself.

Well, a pointer expression is an lvalue if the result pointer of a pointer expression already explicitly has the memory occupied by the pointer itself, otherwise it is not an lvalue. In Example 7, &a is not an lvalue because it does not yet occupy explicit memory. *ptr is an lvalue, because the pointer *ptr already occupies the memory, in fact *ptr is the pointer pa, since pa already has its own place in the memory, then *ptr of course also has its own place.

Five, the relationship between arrays and pointers

The array name of the array can actually be regarded as a pointer. See the following example:

Example nine:

  1. int array[10]={0,1,2,3,4,5,6,7,8,9},value;

  1. value=array[0]; // can also be written as: value=*array;

  1. value=array[3]; //It can also be written as: value=*(array+3);

  1. value=array[4]; // can also be written as: value=*(array+4);

In the above example, generally speaking, the array name array represents the array itself, and the type is int[10], but if the array is regarded as a pointer, it points to the 0th unit of the array, and the type is int* The type pointed to is the type of the array unit, that is, int. So it's no surprise that *array equals 0. Similarly, array+3 is a pointer to the third element of the array, so *(array+3) is equal to 3. Others and so on.

Example ten:

  1. char *str[3]={

  1. "Hello,thisisasample!",

  1. "Hi, good morning.",

  1. "Helloworld"

  1. };

  1. char s[80];

  1. strcpy(s,str[0]); //can also be written as strcpy(s,*str);

  1. strcpy(s,str[1]); //can also be written as strcpy(s,*(str+1));

  1. strcpy(s,str[2]); //can also be written as strcpy(s,*(str+2));

In the above example, str is an array of three elements, and each element of the array is a pointer, and each of these pointers points to a string. If the pointer array name str is regarded as a pointer, it points to unit 0 of the array, its type is char **, and the type it points to is char *.

*str is also a pointer, its type is char *, the type it points to is char, and the address it points to is the address of the first character of the string "Hello, thisisasample!", that is, the address of 'H'. Note: A string is equivalent to an array, which is stored in the form of an array in memory, but the string is an array constant, the content cannot be changed, and it can only be an rvalue. If it is regarded as a pointer, it is both a constant pointer and a pointer constant.

str+1 is also a pointer, it points to the first unit of the array, its type is char**, and the type it points to is char*.

*(str+1) is also a pointer, its type is char*, the type it points to is char, it points to the first character 'H' of "Hi, goodmorning."

Let's summarize the array name of the array (the array is also stored in the array) problem:

If an array TYPE array[n] is declared, the array name array has two meanings:

First, it represents the entire array, and its type is TYPE[n];

Second, it is a constant pointer. The type of the pointer is TYPE*. The type pointed to by the pointer is TYPE, which is the type of the array unit. The memory area pointed to by the pointer is the No. 0 unit of the array. The pointer itself occupies a separate memory area. Note that it is different from the memory area occupied by the No. 0 unit of the array. The value of this pointer cannot be modified, that is, expressions like array++ are wrong. The array name array can play different roles in different expressions. In the expression sizeof(array), the array name array represents the array itself, so the sizeof function measures the size of the entire array.

In the expression *array, array acts as a pointer, so the result of this expression is the value of cell 0 of the array. sizeof(*array) measures the size of the array unit.

In the expression array+n (where n=0, 1, 2, .....), array acts as a pointer, so the result of array+n is a pointer, its type is TYPE *, the type it points to is TYPE, and it points to the nth unit of the array. Therefore, sizeof(array+n) measures the size of the pointer type. In a 32-bit program the result is 4

Example eleven:

  1. int array[10];

  1. int (*ptr)[10];

  1. ptr=&array;

In the above example, ptr is a pointer, its type is int(*)[10], the type it points to is int[10], we use the first address of the entire array to initialize it. In the statement ptr=&array, array represents the array itself.

The function sizeof() is mentioned in this section, so let me ask, does the sizeof (pointer name) measure the size of the type of the pointer itself or the size of the type pointed to by the pointer?

The answer is the former. For example:

int(*ptr)[10];

Then in a 32-bit program, there are:

sizeof(int(*)[10])==4

sizeof(int[10])==40

sizeof(ptr)==4

In fact, sizeof (object) measures the size of the type of the object itself, not the size of any other type.

Six, the relationship between pointers and structure types

A pointer to an object of structure type can be declared.

Example twelve:

  1. struct MyStruct

  1. {

  1. int a;

  1. int b;

  1. int c;

  1. };

  1. struct MyStruct ss={20,30,40};

  1. //declare the structure object ss, and initialize the members of ss to 20, 30 and 40.

  1. struct MyStruct *ptr=&ss;

  1. //Declared a pointer to the structure object ss. Its type is

  1. //MyStruct *, the type it points to is MyStruct.

  1. int *pstr=(int*)&ss;

  1. //Declared a pointer to the structure object ss. But pstr and

  1. // The type ptr it is pointing to is different.

May I ask how to visit the three member variables of ss through the pointer ptr?

Answer:

ptr->a; // point to operator, or these (*ptr).a, it is recommended to use the former

ptr->b;

ptr->c;

Also how to access the three member variables of ss through the pointer pstr?

Answer:

*pstr; //Access member a of ss.

*(pstr+1); //Access member b of ss.

*(pstr+2) //Access member c of ss.

Although I have debugged the above code on my MSVC++6.0, you must know that it is not normal to use pstr to access structure members in this way. To explain why it is not normal, let us see how to access each unit of the array through pointers: (replace the structure with an array)

Example thirteen:

  1. int array[3]={35,56,37};

  1. int *pa=array;

  1. //The method of accessing the three units of the array array through the pointer pa is:

  1. *pa; //visited unit 0

  1. *(pa+1); //visited unit 1

  1. *(pa+2); //visited unit 2

In terms of format, it is the same as the informal method of accessing structure members through pointers.

All C/C++ compilers always store each array unit in a continuous storage area when arranging the units of the array, and there is no gap between the units. However, when storing each member of a structure object, in a certain compilation environment, word alignment or double word alignment or other alignment may be required, and several "filling bytes" need to be added between two adjacent members, which may result in a gap of several bytes between each member.

Therefore, in Example 12, even if *pstr accesses the first member variable a of the structure object ss, there is no guarantee that *(pstr+1) will be able to access the structure member b. Because there may be some stuffing bytes between member a and member b, maybe *(pstr+1) just accesses these stuffing bytes. This also demonstrates the flexibility of pointers. If your purpose is to see if there are padding bytes between the various structure members, hey, this is a good method.

However, the correct way to access structure members by pointers should be the method of using the pointer ptr in Example 12.

Seven, the relationship between pointers and functions

A pointer can be declared as a pointer to a function.

int fun1(char *,int);

int (*pfun1)(char *,int);

pfun1=fun1;

int a=(*pfun1)("abcdefg",7); //Call the function through the function pointer.

Pointers can be used as formal parameters of functions. In a function call statement, pointer expressions can be used as actual parameters.

Example fourteen:

  1. int fun(char *);

  1. how much;

  1. char str[]="abcdefghijklmn";

  1. a=fun(str);

  1. int fun(char *s)

  1. {

  1. int num=0;

  1. for(int i=0;;)

  1. {

  1. num+=*s;s++;

  1. }

  1. return num;

  1. }

The function fun in this example counts the sum of the ASCII code values ​​of each character in a string. As mentioned earlier, the name of the array is also a pointer. In the function call, when str is passed as an actual parameter to the formal parameter s, the value of str is actually passed to s, and the address pointed to by s is the same as the address pointed to by str, but str and s occupy their own storage space. The self-increment operation on s in the function body does not mean the self-increment operation on str at the same time.

8. Pointer type conversion

When we initialize a pointer or assign a value to a pointer, the left side of the assignment number is a pointer, and the right side of the assignment number is a pointer expression. In the examples we mentioned above, in most cases, the type of the pointer is the same as the type of the pointer expression, and the type pointed to by the pointer is the same as the type pointed to by the pointer expression.

Example fifteen:

  1. float f=12.3;

  1. float *fptr=&f;

  1. int *p;

In the above example, what should we do if we want the pointer p to point to the real number f?

Is the following statement used?

p=&f;

wrong. Since the pointer p is of type int *, the type it points to is int. The result of the expression &f is a pointer, the type of the pointer is float *, and the type it points to is float.

The two are inconsistent, and the method of direct assignment is not acceptable. At least on my MSVC++6.0, the assignment statement to the pointer requires that the types on both sides of the assignment number be the same, and the type pointed to is also the same. I haven't tried it on other compilers, so you can try it. In order to achieve our purpose, a "forced type conversion" is required:

p=(int*)&f;

If there is a pointer p, we need to change its type and pointed type to TYEP *TYPE, then the syntax format is: (TYPE *)p;

The result of such forced type conversion is a new pointer, the type of the new pointer is TYPE *, the type it points to is TYPE, and the address it points to is the address pointed to by the original pointer.

And all the properties of the original pointer p are not modified. (remember)

If a function uses a pointer as a formal parameter, then in the process of combining the actual parameter and the formal parameter of the function call statement, the type must be consistent, otherwise it needs to be converted

Example sixteen:

  1. void fun(char*);

  1. int a=125,b;

  1. fun((char*)&a);

  1. void fun(char*s)

  1. {

  1. charc;

  1. c=*(s+3);*(s+3)=*(s+0);*(s+0)=c;

  1. c=*(s+2);*(s+2)=*(s+1);*(s+1)=c;

  1. }

Note that this is a 32-bit program, so the int type occupies four bytes, and the char type occupies one byte. The function of fun is to reverse the order of four bytes of an integer. Have you noticed? In the function call statement, the result of the actual parameter &a is a pointer, its type is int *, and the type it points to is int. The type of the formal parameter this pointer is char *, and the type it points to is char. In this way, in the process of combining actual parameters and formal parameters, we must perform a conversion from int * type to char * type.

Combining this example, we can do this

Imagine the conversion process of the compiler: the compiler first constructs a temporary pointer char *temp, then executes temp=(char *)&a, and finally passes the value of temp to s. So the final result is: the type of s is char *, the type it points to is char, and the address it points to is the first address of a.

We already know that the value of a pointer is the address pointed to by the pointer. In a 32-bit program, the value of a pointer is actually a 32-bit integer.

Can an integer be directly assigned to the pointer as the value of the pointer? Like the following statement:

  1. unsigned int a;

  1. TYPE *ptr; //TYPE is int, char or structure type and so on.

  1. a=20345686;

  1. ptr=20345686; //Our purpose is to make the pointer ptr point to the address 20345686

  1. ptr=a; //Our purpose is to make the pointer ptr point to the address 20345686

  1. //Compile it. It turned out that the latter two sentences were all wrong. So our goal cannot be achieved? No, there is another way:

  1. unsigned int a;

  1. TYPE *ptr; //TYPE is int, char or structure type and so on.

  1. a=N //N must represent a legal address;

  1. ptr=(TYPE*)a; //Hehe, this is all right.

Strictly speaking, (TYPE *) here is not the same as (TYPE *) in pointer type conversion. Here (TYPE*) means to treat the value of the unsigned integer a as an address. The above emphasizes that the value of a must represent a legal address, otherwise, when you use ptr, an illegal operation error will occur. Think about whether it can be reversed, and the address pointed to by the pointer, that is, the value of the pointer, can be taken out as an integer. absolutely okay. The following example demonstrates taking the value of a pointer as an integer, and then assigning the integer as an address to a pointer:

Example seventeen:

  1. int a=123,b;

  1. int *ptr=&a;

  1. char *str;

  1. b=(int)ptr; //take the value of the pointer ptr as an integer.

  1. str=(char*)b; //Assign the value of this integer as an address to the pointer str

Now we know that the value of a pointer can be taken out as an integer, and an integer value can be assigned to a pointer as an address.

Nine, pointer security issues

See the example below:

Example eighteen:

  1. char s='a';

  1. int *ptr;

  1. ptr=(int *)&s;

  1. *ptr=1298;

The pointer ptr is a pointer of type int *, and the type it points to is int. The address it points to is the first address of s. In a 32-bit program, s occupies one byte, and int type occupies four bytes. The last statement not only changes one byte occupied by s, but also changes the three bytes in the high address direction adjacent to s. What are these three bytes for? Only the compiler knows, and the person who wrote the program is unlikely to know. Maybe these three bytes store very important data, maybe these three bytes happen to be a code of the program, and because of your sloppy use of pointers, the value of these three bytes has been changed! This can cause crashing errors.

Let's look at another example:

Example nineteen:

  1. char a;

  1. int *ptr=&a;

  1. ptr++;

  1. *ptr=115;

This example can be compiled and executed completely. But see? In the third sentence, after the self-increment operation is performed on the pointer ptr, ptr points to a storage area in the high address direction adjacent to the integer variable a. What's in this storage area? we do not know. Chances are it's a very important piece of data, maybe even a piece of code.

And the fourth sentence actually writes a data into this storage area! This is a serious mistake. So when using pointers, programmers must be very clear in their hearts: where does my pointer point to. When using pointers to access arrays, be careful not to exceed the low and high boundaries of the array, otherwise similar errors will occur.

In the forced type conversion of the pointer: ptr1=(TYPE *)ptr2, if sizeof (type of ptr2) is greater than sizeof (type of ptr1), then it is safe to use the pointer ptr1 to access the storage area pointed to by ptr2. If sizeof(type of ptr2) is smaller than sizeof(type of ptr1), then it is unsafe to use pointer ptr1 to access the memory area pointed to by ptr2. As for why, readers should think about it in conjunction with Example 18, and they should understand.

Guess you like

Origin blog.csdn.net/cyy1104/article/details/129585567