Second-level pointer Parameters

Source: Internet
Author: User

Procedure 1:
Void mymalloc (char * s) // I want to allocate memory in the function and then return
{
S = (char *) malloc (100 );
}

Void main ()
{
Char * P = NULL;
Mymalloc (p); // here, P is actually null, and the value of P is not changed. Why?
If (p) Free (P );
}
Program 2: void mymalloc (char ** S)
{
* S = (char *) malloc (100 );
}

Void main ()
{
Char * P = NULL;
Mymalloc (& P); // The P here can get the correct value.
If (p) Free (P );
}
Procedure 3:
# Include <stdio. h>

Void fun (int * P)
{
Int B = 100;
P = & B;
}

Main ()
{
Int A = 10;
Int * q;
Q = &;
Printf ("% d/N", * q );
Fun (Q );
Printf ("% d/N", * q );
Return 0;
}
Result:
10
10
Procedure 4:
# Include <stdio. h>

Void fun (int * P)
{
* P = 100;
}

Main ()
{
Int A = 10;
Int * q;
Q = &;
Printf ("% d/N", * q );
Fun (Q );
Printf ("% d/N", * q );
Return 0;
}
Result:
10
100
Why?

---------------------------------------------------------------

1. The allocated memory is the row parameter S, and P does not allocate memory.
2. The allocated memory is the pointer P directed by the row parameter S, so the memory is allocated.
---------------------------------------------------------------

The pointer is not clear, but it is a function call problem! Take a look at this section:

7.4 how does the pointer Parameter Pass the memory?
If the function parameter is a pointer, do not expect this pointer to apply for dynamic memory. In Example 7-4-1, the getmemory (STR, 200) Statement of the test function does not enable STR to obtain the expected memory. STR is still null. Why?

Void getmemory (char * P, int num)
{
P = (char *) malloc (sizeof (char) * num );
}
Void test (void)
{
Char * STR = NULL;
Getmemory (STR, 100); // STR is still null
Strcpy (STR, "hello"); // running error
}
Example 7-4-1 try to apply for dynamic memory with pointer Parameters

Mao is in the getmemory function. The compiler always needs to make a temporary copy for each parameter of the function. The copy of the pointer parameter P is _ p, and the compiler makes _ p = P. If the program in the function body modifies the content of _ p, the content of parameter P is modified accordingly. This is why pointers can be used as output parameters. In this example, _ P applied for a new memory, but changed the memory address indicated by _ p, but P was not changed at all. Therefore, the getmemory function cannot output anything. In fact, each execution of getmemory exposes a piece of memory, because the memory is not released with free.
If you need to use the pointer parameter to request memory, you should use "pointer to Pointer" instead. See example 7-4-2.

Void getmemory2 (char ** P, int num)
{
* P = (char *) malloc (sizeof (char) * num );
}
Void Test2 (void)
{
Char * STR = NULL;
Getmemory2 (& STR, 100); // note that the parameter is & STR, not Str
Strcpy (STR, "hello ");
Cout <STR <Endl;
Free (STR );
}
Example 7-4-2 apply for dynamic memory with a pointer pointing to the pointer

Because the concept of "pointer to Pointer" is not easy to understand, we can use function return values to transmit dynamic memory. This method is simpler. See example 7-4-3.

Char * getmemory3 (INT num)
{
Char * P = (char *) malloc (sizeof (char) * num );
Return P;
}
Void test3 (void)
{
Char * STR = NULL;
STR = getmemory3 (100 );
Strcpy (STR, "hello ");
Cout <STR <Endl;
Free (STR );
}
Example 7-4-3 use the function return value to pass the dynamic memory

Although it is easy to use the function return value to pass dynamic memory, some people often use the return statement wrong. It is emphasized that the return statement should not be used to return the pointer pointing to the "stack memory", because the function exists in it automatically disappears when it ends. See example 7-4-4.

Char * getstring (void)
{
Char P [] = "Hello World ";
Return P; // the compiler will give a warning
}
Void test4 (void)
{
Char * STR = NULL;
STR = getstring (); // STR content is junk
Cout <STR <Endl;
}
Example 7-4-4 Return Statement returns a pointer to "stack memory"

Use the debugger to track test4 step by step. After executing the STR = getstring statement, STR is no longer a null pointer, but the STR content is not "Hello World" but garbage.
What if I rewrite Example 7-4-4 to Example 7-4-5?

Char * getstring2 (void)
{
Char * P = "Hello World ";
Return P;
}
Void test5 (void)
{
Char * STR = NULL;
STR = getstring2 ();
Cout <STR <Endl;
}
Example 7-4-5 return statement returns a constant string

Although test5 does not run properly, the design concept of the getstring2 function is incorrect. Because "Hello World" in getstring2 is a constant string located in the static storage zone, it remains unchanged during the lifetime of the program. No matter when getstring2 is called, it returns the same read-only memory block.

---------------------------------------------------------------

Let's take a look at Lin Rui's "High Quality C/C ++ programming". The above is very clear.
---------------------------------------------------------------

For 1 and 2:
If the input is a level-1 pointer s,
The function will use the copy of S,
To change the value of S, you can only pass a pointer to s, that is, a second-level pointer.

---------------------------------------------------------------

Procedure 1:
Void mymalloc (char * s) // I want to allocate memory in the function and then return
{
S = (char *) malloc (100); // s is a value parameter. After the function returns, it returns the value before the transfer, and cannot return the allocation result.
}
This is the same as calling void func (int I) {I = 1 ;};. Exit the function body and I refers to the recovered

Program 2: void mymalloc (char ** S)
{

* S = (char *) malloc (100); // This is acceptable
}
Equivalent
Void int func (int * PI) {* Pi = 1;} the PI pointer remains unchanged, and the data content pointed to by the pointer changes.
The value parameter itself remains unchanged, but the content of the memory pointed to by the value parameter changes.

Procedure 3:
Void fun (int * P)
{
Int B = 100;
P = & B; // It is equivalent to the first problem. The address of B is not returned.
}

Procedure 4:

Void fun (int * P)
{
* P = 100; // okay
}

---------------------------------------------------------------

In fact, the author's problem has little to do with pointers, that is, the problem of row parameters and value parameters.

When a function is called, the value parameter is passed as a value and will not be returned.
This value is equivalent to a variable in the function body and can be changed, but this change cannot bring out the external function body.

---------------------------------------------------------------

Procedure 1:
Void mymalloc (char * s) // I want to allocate memory in the function and then return
{
S = (char *) malloc (100); // The address referred to by P is not the address of P, so changing s will not change P
}

Void main ()
{
Char * P = NULL;
Mymalloc (p); // here, P is actually null, and the value of P is not changed. Why?
If (p) Free (P );
}
Program 2: void mymalloc (char ** S)
{
* S = (char *) malloc (100); // s points to the P address, so the memory unit referred to by P is changed.
}

Void main ()
{
Char * P = NULL;
Mymalloc (& P); // The P here can get the correct value.
If (p) Free (P );
}
Procedure 3:
# Include <stdio. h>

Void fun (int * P)
{
Int B = 100;
P = & B;
}

Main ()
{
Int A = 10;
Int * q;
Q = &;
Printf ("% d/N", * q );
Fun (Q); // the same as the first program.
Printf ("% d/N", * q );
Return 0;
}
Result:
10
10
Procedure 4:
# Include <stdio. h>

Void fun (int * P)
{
* P = 100; // The parameter P and the real parameter P indicate the same memory unit. Therefore, if the content of the memory unit of parameter P is changed, the real parameter is changed.
// Memory unit content
}

Main ()
{
Int A = 10;
Int * q;
Q = &;
Printf ("% d/N", * q );
Fun (Q );
Printf ("% d/N", * q );
Return 0;
}
Result:
10
100
Why?
---------------------------------------------------------------

Void main ()
{
Char * P = NULL;
Mymalloc (p); // here, P is actually null, and the value of P is not changed. Why?
If (p) Free (P );
}

Void mymalloc (char * s) // I want to allocate memory in the function and then return
{
S = (char *) malloc (100 );
}

Execution Process of mymalloc (P:
Assign a temporary variable char * s. The value of S is equal to P, which is null, but s occupies a different memory space than P. Since then, the execution of the function has nothing to do with p! Only the value of P is used to initialize S.
Then, S = (char *) malloc (100) assigns the value of S to the address of malloc, which has no effect on the value of P. The value of P is null.
Note that the pointer variable is only a special variable. In fact, it stores an integer, but it is an address in the memory. It can be used to access this address.

Program 2: void mymalloc (char ** S)
{
* S = (char *) malloc (100 );
}

Void main ()
{
Char * P = NULL;
Mymalloc (& P); // The P here can get the correct value.
If (p) Free (P );
}
Program 2 is correct. Why? Read the execution process and you will know:
Mymalloc (& P); input the address of P to the function. If the address of the stored P variable is 0x5555, the address 0x5555 stores the value of the pointer Variable P, that is, ox5555 points to P.
A temporary variable char *** S is also allocated during the call. The value of S is 0x5555, but the space occupied by S is another space, but it points to an address: ox5555.
* S = (char *) malloc (100); this statement means to assign the value pointed to by s, that is, the value of the variable at the position 0x5555 to (char *) malloc (100), while 0x5555 is stored on the pointer Variable P, so the value of P is changed to the value of (char *) malloc (100. That is, the value of P is the starting address of the newly allocated memory.

This problem is a bit difficult to understand. The key is to assign a copy when the variable is called as a function parameter, whether it is to pass the value or to the address. After the parameter is passed in, the parameter value does not change. Mymalloc (p) does not change the value of P. The value of P is null. It can only change the value of the memory address pointed to by P. But why does mymalloc (& P) work? It does not change (& P) or the value cannot be changed, but it can change the value (& P) pointing to the memory address, that is, the value of P.

---------------------------------------------------------------

What you need to understand is the pointer variable and the variable referred to by the pointer (possibly a piece of memory ).

Pointer variables are stored as common variables,

 

//////////////////////////////////////// //////////////////////////

 

1. It is very easy to apply for memory in the function. The standard usage is fine:
Test ()
{
Int * array;
 
Array = (int *) malloc (sizeof (INT) * 10); // apply for 10*4 bytes, that is, 10 int memory units
}
Note: The use of malloc is simple, but pay attention to the parameters and return values. The parameters are the number of bytes applied for memory, and the number of multi-byte types such as int, short, and float must be multiplied by the number of bytes, the returned value is a pointer with no defined type. You must specify it yourself when using it. 2. Use a level-1 pointer to implement memory application. Use the function return value to bring out the malloc address:
Char * my_malloc (INT m)
{
Char * P;
P = malloc (m );
Return P;
}
Test ()
{
Char * buff = NULL; // if the pointer is not assigned a value in the function, note that the value is null.
Buff = my_malloc (10); printf ("Buff Adress is % x/N", buff); free (buff );
} 3. Use a second-level pointer to implement memory application. Pass the pointer value: void my_malloc1 (char ** P1)
{
* P1 = (char *) malloc (100 );
}
Test ()
{
Char * buffer = NULL;
 
My_malloc1 (& buffer); printf ("buffer Adress is % x/N", buffer); free (buffer );
} Conclusion: the first-level pointer and second-level pointer are different in form parameters: the pointer is used as a form parameter. If the pointer address is changed, the value cannot be returned. If the pointer content is changed and the address remains unchanged, the value can be returned. (Special Case: You can also return the returned value when changing the pointer address)
For a level-1 pointer, the input address is used as a parameter. If the function only changes the content of the pointer, OK, the pointer can be returned normally. If the function changes the pointer address, unless the pointer is returned, otherwise, the pointer cannot be returned normally, and the pointer operation in the function will be invalid.
For the second-level pointer, the input address is used when the form parameter is used (note that the second-level pointer address is passed in at this time). If the second-level pointer address is changed (** P ), the operation on the pointer will also be invalid, but if the content of the second-level pointer is changed (for example, * P), the second-level pointer can be returned normally. In short, the most important thing to use a pointer is to clarify the address and content. When the pointer is a form parameter, it can be returned normally only when its content is changed. 4. programming example :/*
Data: 20100823
File Name: my_pointer.c
Description: The pointer is used as the parameter value transfer analysis.
Result:
1. when a pointer acts as a parameter, if you only need to change the value pointed to by the pointer, you can use a level-1 pointer. If you need to change the address of the pointer itself, you need to use a level-2 pointer, it is equivalent to changing the value pointed to by the first-level pointer.
2. when a pointer is used as a parameter, the changes in the content pointed to by the pointer can be brought back, and the changes in the pointer address cannot be brought back. That is, the address of the pointer as a parameter cannot be changed, otherwise, the real parameter value cannot be returned.
*//************************************* **************************************** ****/
// The pointer acts as a form parameter, and the content pointed to by the pointer changes. This change can be brought back when the function returns.
Void change (int * P)
{
* P + = 5;
} Test1 ()
{
Int A = 1;
 
Change (& );
 
Printf ("after change a is % d/N", a); // The result is 6.
}/************************************** **************************************** ***/
// The pointer is used as the form parameter, and the address of the pointer itself changes. This change will be invalid when the function returns.
Void my_malloc (char * PP, int num)
{
Pp = (char *) malloc (Num );
} Test2 ()
{
Char * Buf = NULL;
 
My_malloc (BUF, 100 );
 
Printf ("after my_malloc Buf Adress is % x/N", Buf); // After the function returns, the Buf address is still null
Strcpy (BUF, "hello"); // This error occurs. When a segment error occurs during running, the program exits directly, and the output below does not exist.
Puts (BUF );
} Main ()
{
Test1 ();
// Test2 ();
}

 

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.