Chapter 1 pointer Concept
A pointer is a special variable. The value stored in it is interpreted as an address in the memory.
To understand a pointer, we need to understand the four aspects of the pointer: pointer type, pointer pointing
Type, pointer value, memory zone pointed to by pointer, and memory zone occupied by pointer. Let
We describe them separately.
First, declare several pointers for example:
Example 1:
(1) int * ptr;
(2) char * ptr;
(3) int ** ptr;
(4) int (* ptr) [3];
(5) int * (* ptr) [4];
If you do not understand the last few examples, please refer to the articles I posted some time ago? Lt; ++ Complex type declaration>.
1. pointer type.
From the perspective of syntax, you only need to remove the pointer name in the pointer declaration statement, and the rest is
Is the type of this pointer. This is the type of the pointer. Let's take a look at
Type:
(1) int * ptr; // the pointer type is int *
(2) char * ptr; // the pointer type is char *
(3) int ** ptr; // the pointer type is int **
(4) int (* ptr) [3]; // the pointer type is int (*) [3]
(5) int * (* ptr) [4]; // the pointer type is int * (*) [4]
How is it? Is it easy to find the pointer type?
2. the type pointed to by the pointer.
When you access the memory area pointed to by the pointer, the type pointed to by the pointer determines the compilation
The content in the memory area is treated as something.
In terms of syntax, you only need to declare the pointer name in the pointer declaration statement and the pointer declaration character on the left of the name.
* Remove, and the rest is the type pointed to by the pointer. For example:
(1) int * ptr; // The Pointer Points to an int type.
(2) char * ptr; // The Pointer Points to a char type.
(3) int ** ptr; // The type pointed to by the pointer is int *
(4) int (* ptr) [3]; // The type pointed to by the pointer is int () [3]
(5) int * (* ptr) [4]; // The type pointed to by the pointer is int * () [4]
In pointer arithmetic operations, the type pointed to by the pointer has a great effect.
The pointer type (the pointer type) and the pointer type are two concepts. When you
The more familiar you are, the more you will find that the concept of "type" that is mixed with pointers is divided into "pointer
The two concepts of "type" and "Type pointed to by Pointer" are one of the key points to be proficient in pointers. I can't
When I found some poorly written books, I stirred up the two concepts of pointers, so I started reading books.
The more you see, the more confused you are.
3. the pointer value, or the memory zone or address pointed to by the pointer.
The pointer value is the value stored by the pointer. The value will be treated as an address by the compiler instead
A common value. In a 32-bit program, the value of all types of pointers is a 32-bit integer, because
In 32-bit programs, all the memory addresses are 32-bit long.
The memory area pointed to by the pointer starts from the memory address represented by the pointer value, and the length is si.
A memory area of zeof (the type pointed to by the pointer. Later, we will say that the value of a pointer is XX.
When the pointer points to a memory area with the XX address as the header, we say that a pointer points to a block
In the memory area, the pointer value is the first address of the memory area.
The memory zone pointed to by the pointer and the type pointed to by the pointer are two completely different concepts. In example 1
The type to which the Pointer Points already exists, but the pointer has not been initialized, so it points to the memory Zone
It does not exist, or it is meaningless.
In the future, every time you encounter a pointer, you should ask: What is the type of this pointer? Pointer
What is the type? Where does this pointer point?
4. The memory occupied by the pointer itself.
How much memory does the pointer occupy? You only need to use the sizeof function (pointer type) to test it.
. On a 32-bit platform, the pointer occupies 4 bytes.
The memory occupied by pointers can be used to determine whether a pointer expression is left.
Chapter 2 arithmetic operations of pointers
The pointer can be added or subtracted from an integer. The meaning of this operation of pointer and addition and subtraction of common values
The meaning of the operation is different. For example:
Example 2:
1. char a [20];
2. int * ptr =;
...
...
3. ptr ++;
In the preceding example, the pointer ptr is of the int type * and it points to the int type. It is initialized to point to the integer.
Variable. In the next 3rd sentences, the pointer ptr is added with 1, and the compiler processes the pointer as follows:
If sizeof (int) is added to the ptr value, 4 is added to the 32-bit program. Because the address is in bytes
Therefore, the address pointed to by ptr is increased by four bytes from the address of the original variable a to the high address.
Since the length of the char type is one byte, the ptr originally points to the unit 0th of array.
Four bytes, pointing to the four bytes starting from Unit 4th in array.
We can use a pointer and a loop to traverse an array. For example:
Example 3:
Example 3:
Int array [20];
Int * ptr = array;
...
// The code for assigning values to integer arrays is omitted here.
...
For (I = 0; I <20; I ++)
{
(* Ptr) ++;
Ptr ++;
}
In this example, the value of each unit in the integer array is added to 1. Since every loop adds the pointer ptr to 1
In each loop, the next unit of the array can be accessed.
Let's look at the example:
Example 4:
1. char a [20];
2. int * ptr =;
...
...
3. ptr + = 5;
In this example, ptr is added with 5, and the compiler processes it like this: add the value of the pointer ptr to 5
By sizeof (int), in a 32-bit program, we add 5 multiplied by 4 = 20. Because the unit of the address is byte
The current ptr points to a higher address than the address pointed to by the ptr after the addition of 5.
20 bytes. In this example, the ptr before 5 is not added to four bytes starting from Unit 0th of array.
After adding 5, ptr has pointed out the valid range of array. Although this problem may occur in applications
But it is syntactically acceptable. This also reflects the flexibility of pointers.
In the preceding example, if ptr is subtracted from 5, the processing process is similar, except that the ptr value is subtracted.
Go to the 5-byte sizeof (int). The new ptr points to a lower address than the original ptr points.
20 bytes to be moved.
To sum up, after a pointer ptrold is added with an integer n, the result is a new pointer ptrnew,
The ptrnew type is the same as the ptrold type.
The same is true. The value of ptrnew is increased by n multiplication sizeof (type pointed to by ptrold) characters than the value of ptrold.
Section. That is to say, ptrnew will point to a greater memory area than the memory area pointed to by ptrold.
The number of n-byte multiplied by sizeof (the type pointed by ptrold.
After a pointer ptrold is subtracted from an integer n, the result is a new pointer ptrnew, ptrnew class.
Type and ptrold are of the same type, and ptrnew is of the same type as ptrold. Pt
The value of rnew will be less than the value of ptrold by n multiplied by sizeof (type indicated by ptrold) bytes, that is
, Ptrnew points to the memory area than the ptrold points to the memory area to move n by siz to the low address direction
Eof (the type indicated by ptrold) bytes.
Chapter 3 operator numbers & and *
Here & is the address operator, * is... the book is called "indirect operator ".
& The operation result of a is a pointer. the pointer type is the type of a plus *.
Is the type of a. The Pointer Points to the address, that is, the address of.
* P's computation results are varied. In short, the result of * p is what p points.
Some features: its type is p-pointed, and its occupied address is p-pointed.
Example 5:
Int a = 12;
Int B;
Int * p;
Int ** ptr;
P = & a; // The result of & a is a pointer of the int type * and the int type.
Is the address of.
* P = 24; // * p result. Here its type is int, and the address it occupies is the location pointed to by p.
Obviously, * p is variable.
Ptr = & p; // The result of & p is a pointer. the pointer type is p type plus *. Here it is int
**. The Pointer Points to the p type. Here it is int *. The Pointer Points to the address of the pointer.
P's own address.
* Ptr = & B; // * ptr is a pointer, and the result of & B is also a pointer. The types and
The type is the same, so it is no problem to assign a value to * ptr with & B.
** Ptr = 34; // * the ptr result is what ptr points to. Here it is a pointer
The result of the X operation is an int type variable.
Chapter 4 pointer expression
If the final result of an expression is a pointer, this expression is called a pointer expression.
Below are some examples of pointer expressions:
Example 6:
Int a, B;
Int array [10];
Int * pa;
Pa = & a; // & a is a pointer expression.
Int ** ptr = & pa; // & pa is also a pointer expression.
* Ptr = & B; // * ptr and & B are pointer expressions.
Pa = array;
Pa ++; // This is also a pointer expression.
Example 7:
Char * arr [20];
Char ** parr = arr; // If arr is regarded as a pointer, arr is also a pointer expression.
Char * str;
Str = * parr; // * parr is a pointer expression.
Str = * (parr + 1); // * (parr + 1) is a pointer expression.
Str = * (parr + 2); // * (parr + 2) is a pointer expression.
Since the result of a pointer expression is a pointer, the pointer expression also has four
Elements: pointer type, pointer pointing type, pointer pointing memory zone, pointer occupied
Memory.
Well, when the result pointer of a pointer expression has clearly occupied the memory of the pointer itself
The pointer expression is a left value, otherwise it is not a left value.
In Example 7, & a is not a left value because it does not occupy clear memory. * Ptr is a left
Value, because the * ptr pointer occupies the memory, in fact * ptr is the pointer pa, since pa is already included
* Ptr also has its own location.
Chapter 5 relationship between arrays and pointers
If you do not understand the statements for declaring arrays, refer to the articles I posted earlier? Lt; Understand the complex types of c and c ++ statements>.
The array name can be regarded as a pointer. See the following example:
Example 8:
Int array [10] = {,}, value;
...
...
Value = array [0]; // It can also be written as: value = * array;
Value = array [3]; // It can also be written as: value = * (array + 3 );
Value = array [4]; // It can also be written as: value = * (array + 4 );
In the preceding example, the array name array represents the array, and the type is int [10 ].
If rray is a pointer, it points to the 0th units of the array. The type is int *, and the type is number.
The group unit type is int. Therefore, it is not surprising that * array is equal to 0. Similarly, array + 3 is
The pointer pointing to the array's 3rd units, so * (array + 3) is equal to 3. Others.
Example 9:
Example 9:
Char * str [3] = {
"Hello, this is a sample! ",
"Hi, good morning .",
"Hello world"
};
Char s [80];
Strcpy (s, str [0]); // It can also be written as strcpy (s, * str );
Strcpy (s, str [1]); // It can also be written as strcpy (s, * (str + 1 ));
Strcpy (s, str [2]); // It can also be written as strcpy (s, * (str + 2 ));
In the preceding example, str is an array of three elements, each of which is a pointer.
Each needle points to a string. If the pointer array name str is used as a pointer, it points to the array No. 0th.
Unit. Its type is char **, and it points to char *.
* Str is also a pointer. Its type is char * and it points to char, which points to the location
The address is the string "Hello, this is a sample! ", That is, the address of 'H.
Str + 1 is also a pointer that points to unit 1st of the array. Its type is char **, which points
Is char *.
* (Str + 1) is also a pointer. Its type is char *, and it points to char.
The first character 'h' of "Hi, good morning.", and so on.
The following is a summary of the array name problem. If an array TYPE array [n] is declared
The name array has two meanings: First, it represents the entire array, and its TYPE is TYPE [n]; second
, It is a pointer, the pointer TYPE is TYPE *, the pointer to the TYPE is TYPE, that is, the array
The type of the Unit. The memory area pointed to by the pointer is the unit 0th of the array. the pointer occupies a separate
Memory zone. Note that it is different from the memory zone occupied by the array unit 0th. The pointer value cannot be modified.
That is, the expression similar to array ++ is incorrect.
In different expressions, array names can play different roles.
In the expression sizeof (array), the array name array represents the array itself, so the sizeof Function
Measure 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 unit 0. Sizeof (* array) measures the size of the array unit.
Expression array + n (where n = 0, 1, 2 ,.....) Array is a pointer, so arr
The result of ay + n is a pointer whose TYPE is TYPE *. It points to TYPE, which points to
Unit n. Therefore, sizeof (array + n) measures the pointer size.
Example 10:
Int array [10];
Int (* ptr) [10];
Ptr = & array;
In the above example, ptr is a pointer and its type is int (*) [10]. It points to int [10].
, We use the first address of the entire array to initialize it. In the statement ptr = & array, array represents the array.
Body.
This section describes the sizeof () function.
Is it the size of the pointer's own type or the size of the type pointed to by the pointer? The answer is the former. For example:
Int (* ptr) [10];
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 object's own type, rather
Type.
Chapter 6 Relationship Between pointers and Structure Types
You can declare a pointer to a structure object.
Example 11:
Struct MyStruct
{
Int;
Int B;
Int c;
}
MyStruct ss = {20, 30, 40}; // declares the structure object ss, and initializes the three members of the ss
To 20, 30, and 40.
MyStruct * ptr = & ss; // declares a pointer to the structure object ss. Its type is
MyStruct *, which points to the type of MyStruct.
Int * pstr = (int *) & ss; // declares a pointer to the structure object ss. But its
Type is different from the type it points to and ptr.
How can I access the three member variables of ss through the pointer ptr?
Answer:
Ptr->;
Ptr-> B;
Ptr-> c;
How can I access the three member variables of ss through the pointer pstr?
Answer:
* Pstr; // access a, a member of the ss.
* (Pstr + 1); // access B, a member of ss.
* (Pstr + 2) // access the ss member c.
Haha, although I have adjusted the above Code on my MSVC ++ 6.0, you must know that using p
The access to structure members by str is not formal. To explain why it is not formal, let's see how
To access each unit of the array:
Example 12:
Int array [3] = {35, 56, 37 };
Int * pa = array;
The method to access the three elements of the array through pointer pa is as follows:
* Pa; // access to unit 0th
* (Pa + 1); // access to unit 1st
* (Pa + 2); // access to unit 2nd
The format is the same as the format of the informal method used to access structure members through pointers.
When all C/C ++ compilers arrange the elements of an array, they always store the elements in a continuous array.
There is no gap between the Unit and the unit in the storage area. However, when each member of a structure object is stored
In the compiling environment, you may need word alignment, double-word alignment, or other alignment.
How many members are added? Quot; fill Byte ", which may lead to several bytes between each Member
.
Therefore, in example 12, even if * pstr accesses the first member variable a of the structure object ss
It is not guaranteed that * (pstr + 1) will be able to access structure member B. Because members a and B may have
Several Padding Bytes. Maybe * (pstr + 1) can access these padding bytes. This also proves that
Needle flexibility. If your goal is to see whether there are any bytes filled with each structure member,
Hey, this is a good method.
The correct method for accessing structure members through pointers is to use the pointer ptr method in example 12.
Chapter 7 relationship between pointers and functions
You can declare a pointer as a pointer to a function.
Int fun1 (char *, int );
Int (* pfun1) (char *, int );
Pfun1 = fun1;
....
....
Int a = (* pfun1) ("abcdefg", 7); // call a function through a function pointer.
You can use pointers as function parameters. In function call statements, pointer expressions can be used
Real parameters.
Example 13:
Int fun (char *);
Int;
Char str [] = "abcdefghijklmn ";
A = fun (str );
...
...
Int fun (char * s)
{
Int num = 0;
For (int I = 0; I
{
Num + = * s; s ++;
}
Return num;
)
In this example, function fun counts the sum of the ASCII values of each character in a string. As mentioned above
The array name is also a pointer. In function calls, after str is passed to the form parameter s as a real Parameter
Actually, the str value is passed to s. The address pointed by s is the same as the address pointed by str,
Str and s occupy their respective storage space. In the function body, performing the auto-increment 1 operation on s does not mean the same
'Str.
Chapter 8 pointer type conversion
When we initialize a pointer or assign a value to a pointer, the left side of the value is a pointer
The right side of the value is a pointer expression. In most cases
The type of the needle is the same as that of the pointer expression.
The types are the same.
Example 14:
1. float f = 12.3;
2. float * fptr = & f;
3. int * p;
In the above example, if we want to point the pointer p to the real number f, what should we do? Use the following
Statement?
P = & f;
No. Because the pointer p is of the int type *, it points to the int type. The result of Expression & f is 1.
Pointer. the pointer type is float * and it points to float. The two are inconsistent.
The method is not feasible. At least in my MSVC ++ 6.0, the pointer assignment statement requires classes on both sides of the assignment number.
Type consistency, pointing to the same type. I have not tried it on other compilers. You can try it. To
To achieve our goal, we need to perform "forced type conversion ":
P = (int *) & f;
If there is a pointer p, we need to change its TYPE and the TYPE to TYEP * and TYPE,
The syntax format is:
(TYPE *) p;
In this way, the forced TYPE conversion result is a new pointer. the TYPE of the new pointer is TYPE *, which points
The TYPE is TYPE, and it points to the address that the original Pointer Points. All attributes of the original pointer p are
Not modified.
If a function uses a pointer as a parameter
During the merging process, pointer type conversion also occurs.
Example 15:
Void fun (char *);
Int a = 125, B;
Fun (char *) & );
...
...
Void fun (char * s)
{
Char c;
C = * (s + 3); * (s + 3) = * (s + 0); * (s + 0) = c;
C = * (s + 2); * (s + 2) = * (s + 1); * (s + 1) = c;
}
}
Note that this is a 32-bit program, so the int type occupies four bytes, And the char type occupies one byte. Letter
Shufun is used to reverse the order of four bytes of an integer. Have you noticed? In function call
In the statement, the result of the real parameter & a is a pointer, whose type is int *, and its type is int. Shape
The pointer type is char *, which points to char. In this way, the combination of real parameters and form parameters
In the process, we must perform a conversion from int * type to char * type. In combination with this example, we can
In this way, we can imagine the conversion process of the compiler: the compiler first constructs a temporary pointer char * temp,
Run temp = (char *) & a, and then pass the temp value to s. So the final result is: s
The type is char *, and it points to char, which points to the first address of.
We already know that the pointer value is the address pointed to by the pointer. In a 32-bit program, the value of the pointer is
It is a 32-bit integer. Can an integer be directly assigned to the pointer as the pointer value? Just like
The following statement:
Unsigned int;
TYPE * ptr; // The TYPE is int, char, or structure TYPE.
...
...
A = 20345686;
Ptr = 20345686; // Our purpose is to point the pointer ptr to the address 20345686 (decimal
)
Ptr = a; // Our purpose is to point the pointer ptr to the address 20345686 (decimal)
Compile it. The result shows that the last two statements are all incorrect. Then our goal cannot be achieved
? No, there are other methods:
Unsigned int;
TYPE * ptr; // The TYPE is int, char, or structure TYPE.
...
...
A = a certain number, which must represent a valid address;
Ptr = (TYPE *) a; // Ha, this is OK.
Strictly speaking, the TYPE * here is different from the TYPE * in the pointer TYPE conversion. Here (TYP
E *) means to treat the value of the unsigned integer a as an address.
The value of a must represent a valid address. Otherwise, when you use ptr
Is invalid.
Think about whether or not we can take the address pointed to by the pointer as an integer. End
Yes. The following example shows how to take the value of a pointer as an integer and then
An integer is assigned to a pointer as an address:
Example 16:
Int a = 123, B;
Int * ptr = &;
Char * str;
B = (int) ptr; // take the pointer ptr value as an integer.
Str = (char *) B; // assign the value of this integer to the pointer str as an address.
Now we know that we can take the pointer value as an integer or
Assign an integer as an address to a pointer.
Chapter 9 pointer Security
See the following example:
Example 17:
Char s = 'a ';
Int * ptr;
Ptr = (int *) & s;
* Ptr = 1298;
Pointer ptr is an int * type pointer, which points to the int type. It points to the address of s.
First address. In 32-bit programs, s occupies one byte, And the int type occupies four bytes. The last statement not only
This changes the size of one byte of s, and also the three byte adjacent to s's high address direction. These three
What are the bytes? Only the compiled program knows, but the program writer is unlikely to know. Maybe
These three bytes store very important data. Maybe these three bytes are exactly a piece of code of the program.
Because of your sloppy application of pointers, the values of these three bytes are changed! This will cause a collapse error.
Error.
Let's take another example:
Example 18:
1. char;
2. int * ptr = &;
...
...
3. ptr ++;
4. * ptr = 115;
This example can be fully compiled and executed. But do you see? 3rd Statement on Pointer ptr
After the auto-increment 1 operation, ptr points to a storage area adjacent to the high address direction of the shaping variable. This storage
What is in the partition? We don't know. It may be a very important data, or even a generation.
. The first sentence is to write a piece of data into this bucket! This is a serious error. Therefore
The programmer must know exactly where my Pointer Points.
When using pointers to access arrays, be sure not to go beyond the low-end and high-end boundaries of arrays. Otherwise
It will also cause similar errors.
In the forced TYPE conversion of pointer: ptr1 = (TYPE *) ptr2, if sizeof (ptr2 TYPE) is large
In sizeof (ptr1 type), when ptr1 is used to access the bucket pointed to by ptr2
All. If sizeof (ptr2 type) is smaller than sizeof (ptr1 type), the pointer ptr1 is used.
It is not safe to access the bucket to which ptr2 points. As for why, the reader may come up with example 17.
Think, it should be clear.