Reprint address http://blog.renren.com/share/425935703/14545505748? From = 0101010202 & ref = hotnewsfeed & sfet = 102 & fin = 48 & FID = 20050008831 & ff_id = 425935703
Char * P, ** P, *** P;
Char P [], p [] [], p [] [] [];
Char * P [], * P [] [], ** P [], ** P [] [], * (* P) [], (** P) [], (** p) [] [];
Void (* pfun) (int I );
The gods must be as clear and clear as the blue sky and white clouds in their heads...
(1) storage of pointers and Arrays
A. Storage of pointers and arrays in memory
When the array P [N] is created, it corresponds to the allocation of an array space in the memory. Its address and capacity cannot be changed in the array lifecycle. Array name P is a constant, that is, the address value for allocating the array space. This value is replaced with a constant during compilation, and there is no memory space to store this value during runtime, it exists with the array length in the Code (it should be a symbol table) and has been formulated during the link. When the pointer * P is created, it corresponds to the space allocation of the pointer variable in the memory, the value entered in the space, that is, the value of the pointer variable, depends on how it is initialized in the program. This also determines the memory address to which the Pointer Points.
The picture is really ugly, but the full text is just a picture. Let's take a look.
B. Assignment and initialization of pointers and Arrays
According to the above, under normal circumstances, the address of the array cannot be modified, the content can be modified; the content of the pointer can be modified, and the content pointed to by the pointer can also be modified, but the pointer should be initialized before that.
For example:
Int P [5];
P = p + 1; Not Allowed
P [0] = 1; yes;
//
Int * P;
P = p + 1; yes
P [0] = 1; is not allowed because the pointer is not initialized;
//
Int I;
Int * P = & I;
P [0] = 1; yes;
Character pointers are also quite special.
For example:
Char * P = "ABC ";
P [0] = 'D'; Not Allowed
Why can't the initialized character pointer change the content it points? This is because P points to a "constant" string, and the string "ABC" is actually stored in the static storage area of the program, so the content cannot be changed. Here, the address of the constant string is determined first, and the pointer is directed to its rear.
While
Char P [] = "ABC ";
P [0] = 'D'; yes
This is because this initialization actually assigns constants to the array directly, that is, writing to the memory space allocated for the array. Here, the Array Memory is allocated first, and the value is assigned after.
(2) meanings of some expressions
Char * P, ** P, *** P;
Char P [], p [] [], p [] [] [];
Char * P [], * P [] [], ** P [], ** P [] [], * (* P) [], (** P) [], (** p) [] [];
Can you clearly understand the meaning of the above expressions? (Dead !)
First group: char * P, ** P, ** P;
They are char pointers, char * pointers, that is, pointers to char * Data addresses, and char ** pointers, that is, pointers to Char ** data; they are all pointers that occupy 4 bytes of space.
For example:
Char c = 'a ';
Char * P = & C;
Char ** p1 = & P;
Char *** P2 = & P1;
Cout <*** P2 <Endl;
Second group: Char P [], p [] [], p [] [] [];
It is a one-dimensional, 2d, and 3D char array, that is, an array, an array, and an array of <array>. You can perform initialization as follows:
Char PP [3] = "AB ";
Char PP1 [3] [3] = {"AB "};
Char PP2 [3] [3] [3] = {"AB "}};
Now we try to assign values to the first group of three pointers using the three array names in the second group. The direct assignment result is as follows:
P = pp; // correct
P1 = PP1; // Error
P2 = PP2; // Error
Why does the assignment of P1 and P2 fail? The reason is that the array name assignment rule is not recursive, that is, the array can assign values to the pointer of the array, rather than to the pointer of the pointer. Here we first understand this abstract rule. The following describes the third group of expressions. We will give an example of this problem after we know how to write the array pointer and pointer array.
Group 3: char * P [], * P [] [], ** P [], ** P [] [], * (* P) [], (** p) [], (** p) [] [];
The method for parsing such expressions is as follows:
First, the entire expression is divided into three parts,
Data Type and star part + P or content in brackets + brackets
For example, char * (* P) [] is divided into char *, (* P), and []
"Char *" indicates the Data Type "(* P)" stored in the innermost layer. "[]" indicates the outermost layer pointer. It indicates the intermediate layer array (dimension = number of braces ), the above expression indicates the pointer P of a one-dimensional array. The data type of the elements in the array is char *. Similarly, char (** p) [] [] indicates a pointer to a two-dimensional array. The data type of the array element is Char. Here, if there is no parentheses in the expression (such as ** P []), it is actually an array. If there is no brackets (such as ** p) at the far right, it is actually a pointer. The meanings of these expressions are described as follows:
Char c = 'a ';
Char * Pc = & C;
Char * P [3], * P1 [3] [3], ** P2 [3], ** P3 [3] [3], * (* P4) [3], (** P5) [3], (** P6) [3] [3], (* P7) [3];
P [1] = pc;
P1 [0] [0] = pc;
P2 [0] = & PC;
P3 [0] [0] = & PC;
(* P4) [0] = pc;
(** P5) [0] = C;
(** P6) [0] [0] = C;
(** P7) [0] = C;
Note that (* P7) [3] and (* P5) [3] are equivalent.
Next, let's continue with the previous Section to discuss the problem of assigning values to pointers by array names.
In fact, the relationship between arrays and pointers that can be assigned values is as follows (--> indicates "assign "):
Array --> pointer: P [] --> * P
Pointer array --> pointer: * P [] --> ** P
--> Pointer: ** P [] --> *** P
......
Or
Array --> array pointer: P [] [] --> (* P) []
--> Pointer to the array: P [] [] [] --> (* P) [] []
In short, the outermost array can convert the pointer to the inner layer without recursion.
(3) Length of the above expression
Evaluate the "length" of an expression. First, distinguish whether the expression actually represents an array or a pointer. If it is a pointer, the length is 4 bytes; if it is an array, You need to calculate the total number of actually stored elements and the Data Type of the elements. In addition, you must pay attention to the number of array elements or the total number of bytes of the array;
For example:
* (* P) [3] [3]
The above formula indicates a pointer, so the length is 4 bytes.
** P3 [3] [3]
Represents a two-dimensional array, the array element type is pointer, so the length is 3*3*4 = 36;
Note that the sizeof function in Standard C calculates the total number of bytes rather than the array length.
(4) pointer return values and pointer parameters of functions
The pointer as the return value should be noted that the pointer of local data should not be returned.
For example:
Char * Fun (void)
{
Char I = 'a ';
Return (& I );
}
When function fun is called, the value 'a' is not obtained because local data (in the stack) is destructed after the function is returned, data memory is recycled, and the data pointed to by the pointer is meaningless;
You can change it:
Char * Fun (void)
{
Char I = 'a ';
Char * P = (char *) malloc (5 );
If (P! = NULL) {P [0] = I, P [1] = '\ 0 ';}
Return (P );
}
The memory allocated using malloc (in the heap) is still valid after the function returns.
This is not complete yet, because one day I used the following code:
Char * Fun (void)
{
Char * P = "ABC ";
Return (P );
}
It is found that although P is defined as a local variable, the return is correct. Do you still remember the constant string storage location mentioned above? The pointer P actually points to the static data area. The char * P here is equivalent to const char * P. Such data will not be immediately recycled after the function returns.
The pointer is mainly used to modify the data content pointed to by the pointer, but the value of the modified pointer is invalid,
For example
Char * Fun (char * P)
{
Char I = 'a ';
P = (char *) malloc (5 );
P [0] = I;
Return P;
}
Because a copy of the pointer is passed (the shape parameter pointer has the same value as the real parameter pointer, but not the same pointer), it does not affect the real parameter value of the caller. (The strange vs2012 seems to be able to change the value of the real parameter through the form parameter! But don't take the risk ).
(5) const Modifier
The const modifier is also very tangled when used for pointers.
First, you must distinguish const char * P and char * const p.
Const char * P is the pointer to the const object, that is, the object is read-only, but the pointer is not. Note the following two points when using the const Object Pointer:
First, you cannot assign a value to a pointer of a non-const object,
For example:
Const char * P;
Char * P1 = P; // not allowed
Of course, it is not legal to direct a non-const pointer to a const object,
For example:
Const char C;
Char * P1 = & C; // not allowed,
This is to avoid changing the value of the const object through P1.
Second, you can assign a non-const object address to the pointer pointing to the const object, but it is illegal to use this pointer to change the variable value,
For example:
Char c = 'a ';
Const char * P = & C; // allowed
* P = 'B'; // not allowed
Char * const P is a const pointer, that is, pointing to an object that can be edited, but the pointer itself cannot be modified, which is similar to an array.
For example:
Char c = 'a ';
Char * const P = & C;
* P = 'B'; // allowed
P ++; // not allowed
The method to distinguish the two is to check whether the const is close to the pointer name. If yes, the const pointer is used; otherwise, the const object is used. The premise of this note-adding method is that char should be placed together with the * sign, because const char * P = char const * P.
In addition, there is const char * const P, which naturally points to the const pointer of the const object.
(6) pointer Functions
First, pay attention to the difference between a pointer function and a function pointer. The former refers to a function that returns a pointer, which is mentioned above, and the latter refers to a pointer to a function ".
The function pointer is defined by replacing "function name" with "(* function pointer name )",
For example:
The pointer to a function declared as void fun (int A) can be defined as void (* pfun) (int A) or void (* pfun) (INT ), note that the function pointer pfun can only point to a class of functions with the same return type (void) and parameter type (INT) as fun, And the definition () is not a decoration, remove () it is regarded as a function declaration with the return value of void * type. For example:
Void fun (int)
{
Cout <A <Endl;
}
Int main ()
{
Void (* pfun) (INT );
Pfun = & fun; // (1)
* (Pfun) (1); // (2)
}
In fact, the (1) (2) line in the above formula is also correct with the following replacement:
A. pfun = fun;
Pfun (1 );
B. pfun = & fun;
Pfun (1 );
C. pfun = fun;
* (Pfun) (1 );
If you have any questions, try to call the function fun directly in the following way:
(* Fun) (1 );
The running result is correct! How can this be explained?
In fact, fun is not only a function name, but also a function pointer like pfun, but a function pointer constant. For ease of writing, C language developers allow function pointer calls to be directly written in a form similar to fun (). Similarly, function pointer variable assignments can also be written in a form similar to pfun = & fun. It is worth noting that the format of function declaration is still relatively strict, such:
Void fun (INT); // cannot be written as void (* Fun) (INT ).
Similarly,
Void (* pfun) (INT); // It cannot be written as void pfun (INT ).
For convenience, we can also define the function pointer type. The method for defining the above example is as follows:
Typedef void (* pfun) (INT );
In this way, we can use
Pfun;
To declare a function pointer.
With function pointers, function parameters can also be set to a type of function.
For example:
Typedef void (* pfun) (INT );
Void fun (int)
{
Cout <A <Endl;
}
Void topfun (pfun F1, int)
{
F1 ();
}
Int main ()
{
Topfun (fun, 1 );
Return 1;
}