When using a pointer as a parameter to allocate memory in a function, you must be extremely careful in its operations.
================================
# Include <stdio. h>
# Include <string. h>
# Include <stdlib. h>
# Include <iostream. h>
Void fun (int * P)
{
Cout <"Fun 1:" <Endl;
Cout <p <Endl;
Cout <* P <Endl;
P = (int *) malloc (sizeof (INT ));
* P = 2;
Cout <"Fun 2:" <Endl;
Cout <p <Endl;
Cout <* P <Endl;
}
Void main ()
{
Int * P;
P = (int *) malloc (sizeof (INT ));
* P = 1;
Cout <"Main 1:" <Endl;
Cout <p <Endl;
Cout <* P <Endl;
Fun (P );
Cout <"Main 2:" <Endl;
Cout <p <Endl;
Cout <* P <Endl;
}
Running result:
Main 1:
0x00032fa0
1
Fun 1:
0x00032fa0
1
Fun 2:
0x00032fd8
2
Main 2:
0x00032fa0
1
The position of pointer P in the main function is not changed. The P pointer in function fun is the same position as the main function P at the beginning, but the position is different once the memory space is created. Therefore, the value of 1 in the main function is not 2.
If you change the parameter to pointer reference, you can modify the actual parameter. In addition, the parameter P and the parameter P address are the same, that is, the parameter P and the parameter P represent the same meaning. Modifications to parameters are modifications to real parameters, including memory allocation and memory assignment.
As follows:
# Include <stdio. h> <br/> # include <string. h> <br/> # include <stdlib. h> <br/> # include <iostream. h> <br/> void fun (int * & P) <br/> {<br/> cout <"Fun 1:" <Endl; <br/> cout <p <Endl; <br/> cout <* P <Endl; </P> <p> P = (int *) malloc (sizeof (INT); <br/> * P = 2; </P> <p> cout <"Fun 2:" <Endl; <br/> cout <p <Endl; <br/> cout <* P <Endl; <br/>}</P> <p> void main () <br/>{</P> <p> int * P; <br/> P = (int *) malloc (sizeof (INT); <br/> * p = 1; </P> <p> cout <"Main 1:" <Endl; <br/> cout <p <Endl; <br/> cout <* P <Endl; </P> <p> fun (p); </P> <p> cout <"Main 2: "<Endl; <br/> cout <p <Endl; <br/> cout <* P <Endl; </P> <p >}< br/>
# Include <stdio. h>
# Include <string. h>
# Include <stdlib. h>
# Include <iostream. h>
Void fun (int * & P)
{
Cout <"Fun 1:" <Endl;
Cout <p <Endl;
Cout <* P <Endl;
P = (int *) malloc (sizeof (INT ));
* P = 2;
Cout <"Fun 2:" <Endl;
Cout <p <Endl;
Cout <* P <Endl;
}
Void main ()
{
Int * P;
P = (int *) malloc (sizeof (INT ));
* P = 1;
Cout <"Main 1:" <Endl;
Cout <p <Endl;
Cout <* P <Endl;
Fun (P );
Cout <"Main 2:" <Endl;
Cout <p <Endl;
Cout <* P <Endl;
}
The running result is as follows:
Main 1:
0x00032fa0
1
Fun 1:
0x00032fa0
1
Fun 2:
0x00032fd8
2
Main 2:
0x00032fd8
2
Refer to the following online documents:
======================
Void getmemory (char * P)
{
P = (char *) malloc (100 );
}
Void test (void)
{
Char * STR = NULL;
Getmemory (STR );
Strcpy (STR, "Hello World ");
Printf (STR );
} What are the results of running the test function?
A: memory error. getmemory does not allocate memory space to str. P is the replication of STR, and P and STR point to the same memory area.
The above program P copies STR as a null pointer, and then P is allocated to the memory space, while STR is still null, so an error occurs.
You can change it to reference transmission. Or use a pointer instead.
Void getmemory (char * & P)
{
P = (char *) malloc (100 );
}
Char * getmemory (void)
{
Char P [] = "Hello World ";
Return P;
}
Void test (void)
{
Char * STR = NULL;
STR = getmemory ();
Printf (STR );
}
What are the results of running the test function? A:
STR points to a piece of memory that has been released, and the result is incorrect. The pointer P points to the "Hello World" memory which is allocated in the stack and is released after the function ends.
The memory occupied by a C/C ++ compiled program is divided into the following parts:
1. STACK: the stack zone is automatically allocated and released by the compiler, and stores function parameter values and local variable values. The operation is similar
Stack in the data structure.
2. Heap-generally assigned and released by the programmer. If the programmer does not release the heap, it may be recycled by the OS at the end of the program. Pay attention to it and Data
The heap in the structure is similar to the linked list.
3. Global (static)-the storage of global variables and static variables is put together. initialized global variables and static variables
Variables are in one area, and uninitialized global variables and uninitialized static variables are in another adjacent area. After the program ends
Release.
4. Text Constant Area-constant strings are placed here. The program is released by the system.
5. Code Area
This is an example
// Main. cpp
Int A = 0; // global initialization Zone
Char * P1; // not initialized globally
Main ()
{
Int B; stack
Char s [] = "ABC"; // Stack
Char * P2; // Stack
Char * P3 = "123456"; // 123456/0 is in the constant zone, and P3 is in the stack.
Static int C = 0; // global (static) initialization Zone
P1 = (char *) malloc (10 );
P2 = (char *) malloc (20); // The allocated 10-byte and 20-byte areas are in the heap area.
Strcpy (P1, "123456"); // 123456/0 is placed in the constant area, and the compiler may optimize it to "123456" as directed by P3.
-----------------------
When pointer is used as a function parameter for transmission, a problem occurs, and you do not know where to start: the source code is as follows:
Createnode (binnode * tree, char * P)
{
Tree = (binnode *) malloc (sizeof (binnode ));
Tree-> DATA = * P;
}
The purpose of this code segment is to create a node with a binary tree through a function. However, after calling this function, a memory access error occurs when trying to access the members of the node structure, where is the problem?
I have never understood the pointer mechanism as a function parameter value passing mechanism. I opened Lin's "High Quality C/C ++ programming guide" and found the answer.
[If the function parameter is a pointer, do not expect this pointer to apply for dynamic memory]
The original problem lies in the principle of C compiler: the compiler always creates a temporary copy for each parameter of the function. The copy of the pointer parameter tree is _ tree, And the compiler makes _ tree = tree. If the program in the function body modifies the content of the _ tree, the content of the parameter tree will be modified accordingly. This is why pointers can be used as output parameters.
The above function code is compiled:
Createnode (binnode * tree, char * P)
{
Binnode * _ tree;
_ Tree = tree;
_ Tree = (binnode *) malloc (sizeof (binnode ));
_ Tree-> DATA = * P;
}
If no
_ Tree = (binnode *) malloc (sizeof (binnode ));
This statement modifies the content of the _ tree in the function body, which will cause the content of the parameter tree to be modified as they point to the same memory address. While
_ Tree = (binnode *) malloc (sizeof (binnode ));
In this sentence, the system re-allocates the memory to the _ tree pointer, And the _ tree pointer points to the new address allocated by the system. The function body only modifies the _ tree content, it has no effect on the content of the address specified by the original tree. Therefore, when a function parameter is a pointer, do not change the address indicated by the pointer within the function body. This is useless and only the content pointed to by the pointer needs to be modified. That is, the pointer should be treated as a constant.
If you need to use the function pointer to request memory space, you need to use the pointer pointing to the pointer.
Createnode (binnode ** tree, char * P)
{
* Tree = (binnode *) malloc (sizeof (binnode ));
}
The above is Lin Rui's statement. At present, I don't know how to understand it. However, there can be another solution to pass dynamic memory through function return values:
Binnode * createnode ()
{
Binnode * tree;
Tree = (binnode *) malloc (sizeof (binnode ));
Return tree;
}
This is also true because the function returns an address value, which is the first address of the applied memory block. However, this is easy to confuse with another piece of advice.
[Do not use the return statement to return a pointer to the "stack memory" because the function automatically disappears when it ends.]
The differences between static memory, stack memory, and dynamically allocated memory (heap memory) are as follows:
(1) distribution from the static storage area. The program has been allocated when it is compiled, and the program exists throughout the entire runtime. For example, global variables and static variables.
(2) create a stack. When a function is executed, the storage units of local variables in the function can be created on the stack. When the function is executed, these storage units are automatically released. Stack memory allocation computation is built into the processor's instruction set, which is highly efficient, but the memory capacity allocated is limited.
(3) allocate from the stack, also known as dynamic memory allocation. When the program runs, it uses malloc or new to apply for any amount of memory. The programmer is responsible for releasing the memory with free or delete. The lifetime of the dynamic memory is determined by us. It is very flexible to use, but the problem is also the most.
Therefore, an unknown error occurs when an attempt is made to return the memory allocated on a stack.
Char * getstring (void)
{
Char P [] = "Hello World ";
Return P; // the compiler will give a warning
}
P is the memory allocated on the stack. It is automatically released after the function is completed. The content in the memory area pointed by P is not "Hello World", but unknown.
What if the returned static storage memory is:
Char * getstring (void)
{
Char * P = "Hello World ";
Return P;
}
Here "Hello world" is a constant string located in the static storage area, which remains unchanged during the lifetime of the program. No matter when getstring is called, it always returns the same read-only memory block.