[Programming and development] Some analysis caused by pointer Transfer

Source: Internet
Author: User

Yesterday, when a classmate (beginner pointer) was practicing Single-Chain tables and binary trees, the program always crashed or failed to get the correct results, so he asked me for help. The problem lies in the Failover data transfer of the pointer. if the pointer is not passed well, the memory is disordered, and other code is basically all right. This error is a pity. So here I want to make a record, which may be very basic.

Assuming that the number of arguments of a function is a common first-level pointer, it means that you can only use the pointer, change the pointer to or change the target variable. You cannot apply for memory using this pointer.

Void getmemory (int * P) {P = (int *) malloc (sizeof (INT) * 10);} void func () {int * num = NULL; getmemory (Num); // the pointer P is still a null pointer}
This is a common error. When a function is called, the form of a function is always a copy of the actual volume, even a pointer. For example, the above Code can be seen as: when calling a function, assign the target address pointed to by num to the P pointer. Now the num pointer and P pointer are two completely different entities. They point to the same destination address at the same time. The following code verifies this statement.
#include <iostream>using namespace std;void getMemory(int *p){  printf("target address of pointer p is: %x, its value is: %x\n", p, *p);  printf("but address of pointer p itself is: [%x]\n", &p);}int main(){    int val = 4;    printf("address of val is: %x\n", &val);    int *num = &val;    printf("target address of pointer num is:%x, its value is:%x\n", num, *num);    printf("address of pointer num itself is: [%x]\n", &num);    getMemory(num);    // printf("%d %d %d\n", *p, *(p+1), *(p+2));    getchar();    return 0;}
In this way, the p pointer on the Shape struct is a new pointer, which points to the same as the original num pointer, so the variable of the target address can be changed normally and output in the Inbound direction.

Today, the p pointer in the function has applied for a new memory, and now it is very obvious: its behavior has nothing to do with the original pointer, It is the P pointer's own thing.

There are many ways to solve this error. In fact, you can do everything you need. You just need to figure out who used the applied memory.

Method 1: Use a pointer to a pointer

void getMemory(int **p){*p = (int *)malloc(sizeof(int) * 10);}void func(){int *num = NULL;getMemory(&num);}
Why? Let's analyze it. ** P is a pointer to a pointer. As mentioned above, if num and P point to the same target, both num and P can read or modify the target.

In this case, I will directly implement the handler, that is, the num pointer, as my goal.

If you know & P, P, and * P, int ** P is actually not magical. Do you still remember the meaning of int in int * P? Since it is a pointer to a pointer, it should be written as follows: int ** P, because it itself is a pointer and points to an int * type pointer. But I do not recommend writing int ** P. After all, the second-level pointer is very different from the first-level pointer. To highlight the second-level pointer, you should write it: int ** P (some are written as int ** P ).

There is no need to make such confusion at all. The second-level pointer P is a pointer, that's all. The target of the second-level pointer of the operation, that is, * P, is equivalent to the operation pointer num, that is, * P = num. * What does num mean? Add a asterisk (*) before num to indicate the object to which the num Pointer Points. Unfortunately, num points to null, which is not a good description. Because num = * P, * num = * (* P) = ** p.

I believe you should understand * P and ** P very well.

Okay. Let's look back at the Code:

*p = (int *)malloc(sizeof(int) * 10);
* P points to num, that is, num itself. Now let num apply for memory on its own, instead of asking someone else to apply for it on its behalf. Of course, this is correct :)

Method 2: directly apply for a piece of memory, and then return the address to the pointer

The Applied memory is actually very easy. We usually write it like this:

int *pBuffer = (int *)malloc(sizeof(int) * 10);
That is to say, let the operating system arrange a location for me and then tell me the address of the location. It is to return the address of this new memory to the pointer of pbuffer, so that pbuffer can be operated after pointing to this memory. In this case, let the num pointer do this directly. The Code is as follows:

int* getMemory(){int *p = (int *)malloc(sizeof(int) * 10);return p;}void func(){int *num = NULL;num = getMemory();}
This code is easy to understand. In the function, P applies for a piece of memory, then P points to the fast memory, and finally P returns the address of the new memory to the num pointer. This is safe. As mentioned above, the p pointer itself is a local variable of the function and is stored in the stack, but the memory requested by the P pointer is stored in the heap, so P will be released after the function is completed, but this memory block will not. Assuming that the memory block also exists in the stack, it will not work.




It is still not enough to understand the above principles. Let's take a look at the following code:
char* getString(){char *s = "hactrox";return s;}void func(){char *str = NULL;str = getString();}

The character string "hactrox" in the getstring function is stored in the text constant area. As the name suggests, since it is a "constant" area, it must be read only, in other words, no matter what changes are made to this string, they do not agree.

Although the above Code is completely correct, it also hides a large risk at the same time. Only when the STR pointer tries to change the string at any time will the program crash.

Method 3: Reference

First, describe the concept of reference. The C language does not reference the concept, and the & symbol is only used as the address. Reference is a concept in C ++. It is very easy to confuse references with pointers. A reference is an alias.

First, let's look at a common statement that is no longer common:

int value = 10;
This int type variable value is obviously not a pointer. It is a variable name, representing the name of the memory.

int *p = &value;int &nickname = num;
The statement in the second row means that I have created a new item, which is the alias of the num variable. The nickname is neither a variable nor a pointer nor a copy, it is not a string, so it must have a name, right? It is called reference. The difference between a reference and a pointer is that the pointer itself is an entity, and the value holds the number 10 in its hand. The Pointer Points to the number in its hand, and their "common goal" is the number 10. Reference is totally different. For reference, there is no "common goal". Because reference itself is the value itself, there is another name for the value variable.

Some differences between references and pointers are as follows:

1. You can first create a pointer and then point to a target. When creating a reference, you must specify the target. You have to find this person, and then this person has a nickname.

2. For reference, pointers are very free, and pointers can point to a target or null. However, null references are not allowed. This not only violates the original design intention of the reference, but also logically speaking, it just goes. A thing itself does not exist. Where is the nickname? Even if you have a nickname, what is its original name?

3. Once a reference is set up for a variable, the reference is bound to the variable. In other words, this reference cannot point to other variables. Therefore, the reference is equivalent to the attribute of the variable. Imagine that after an employee gets an external number, it is impossible to use this external number to call another person? If this is the case, many people may not know who is calling this nickname, and the system does. So of course it won't work.

#include <iostream>using namespace std;void changeByReference(int &a){    a = 5;}void changeByPointer(int *p){    *p = 8;}int main(){    int val = 5;    changeByReference(val);    printf("%d\n", val);    int num = 12;    changeByPointer(&num);    printf("%d\n", num);    getchar();    return 0;}
With reference, it is as convenient as operating a common variable. Reference A in the above Code does not carry *, and the pointer P must carry * P when using it.

Another advantage of using references is security. The pointer of C ++ is too powerful, which may cause many problems once it is useless. The referenced functions are much weaker, so it is safe to use the referenced functions when such powerful functions are not needed.

Now let's look at how to apply for memory using references:

void getMemory(int *&p){    p = (int *)malloc(sizeof(int) * 10);}void func(){    int *p = NULL;    getMemory(p);}
The Pointer Reference represents the pointer itself, so the reference can be applied to the memory correctly. There is no doubt about this. The remaining question is: how does the pointer reference? Through the above Code, we know that it is * & P.

Let's take a look at the difference between * & P and & * P.

First, parse the int type reference. Because the referenced type must be the type of the target variable, it must be an int, and because it is specified as a reference character, the int type reference is very easy to write. * & P = * (& P). For pointer variables, the referenced type must be pointer type. Therefore, the referenced variable in the above Code must be int * type, the pointer is P. For reference, it is & P. The result is: int * & P, which is not int * & P.

So what is P? & * P = & (* P), * P is the target pointed to by the pointer. & the result of this target variable is "get the target address pointed to by the pointer ", think about it. What else has this address saved? Of course it is the value of the pointer's memory. If the P Pointer Points to the variable num, & * P, P, and & num are equivalent. After learning the concepts of * and &, the pointer can be played freely:

#include <iostream>using namespace std;int main(){    int num = 888;    int *p = &num;        printf("%d %d %d\n", *(*&p), *&num, *(&*p));    printf("%x %x %x\n", &num, &*p, *&p);    getchar();    return 0;}
You may ask, * & P and & * P in the above Code both mean P, when applying for memory, why can I only write * & P and write & * P?

* & P is a reference, and a reference is a type. & * P is an address fetch operation, not a type. It is like int num = 5. In printf, you can write num or 5, but in code, you can only write num but not 5, because num is a type and 5 is not.

[Programming and development] Some analysis caused by pointer Transfer

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.