Let's declare a few pointers as examples:
Example 1:
( 1)int * ptr;
(2)char * ptr;
(3)int * * ptr;
(4)int(* ptr)[3];
(5)int *(* ptr)[4];
If you don't understand the last few examples, please refer to the article I posted some time ago:>.
Pointer type
From a grammatical point of view, you only need to remove the pointer name from the pointer declaration statement, and the rest is the pointer type. This is the type of pointer itself. Let's look at the pointer types in the example 1:
( 1)int * ptr; //The type of pointer is int*
(2)char * ptr; //The type of pointer is char*
(3)int * * ptr; //The type of pointer is int**
(4)int(* ptr)[3]; //The type of pointer is int(*)[3]
(5)int *(* ptr)[4]; //The type of pointer is int*(*)[4]
How's it going? Is it easy to find out the type of pointer?
The type that the pointer points to.
When you access the memory area pointed by the pointer, the type pointed by the pointer determines what the compiler regards the contents of the memory area as.
Syntactically, you only need to remove the pointer name and the pointer declarator * to the left of the name in the pointer declaration statement, and the rest is the type that the pointer points to. For example:
( 1)int * ptr; //The pointer points to the type of int.
(2)char * ptr; //The pointer points to a type of char.
(3)int * * ptr; //The pointer points to the type of int*
(4)int(* ptr)[3]; //The type pointed by the pointer is int()[3]
(5)int *(* ptr)[4]; //The type pointed by the pointer is int*()[4]
In the arithmetic operation of pointer, the type pointed by pointer plays a great role.
The type of pointer (that is, the type of pointer itself) and the type pointed by pointer are two concepts. When you are more and more familiar with C, you will find that dividing the concept of "type" mixed with pointer into two concepts: "type of pointer" and "type pointed by pointer" is one of the key points to master pointer. I have read a lot of books, and found that some poorly written books confuse the two concepts of pointer, so reading books is inconsistent, and the more I read them, the more confused I get.
The value of the pointer, or the memory area or address that the pointer points to.
The value of the pointer is the value stored in the pointer itself, and the compiler will treat it as an address instead of a general value. In 32-bit programs, the values of all types of pointers are 32-bit integers, because the memory addresses in 32-bit programs are all 32 bits long. The memory area pointed by the pointer is a memory area with a length of si zeof starting from the memory address represented by the value of the pointer. In the future, we will say that the value of a pointer is XX, which is equivalent to saying that this pointer points to a memory area with an address starting with XX; When we say that a pointer points to a memory area, it is equivalent to saying that the value of the pointer is the first address of this memory area.
The memory area pointed by a pointer and the type pointed by a pointer are two completely different concepts. In the example 1, the type pointed by the pointer already exists, but because the pointer has not been initialized, the memory area it points to does not exist or is meaningless.
Every time you encounter a pointer in the future, you should ask: What type is this pointer? What is the type of pointer? Where does the pointer point?
The memory area occupied by the pointer itself.
How much memory does the pointer itself occupy? You just need to use the function sizeof (the type of pointer) to measure it. In a 32-bit platform, the pointer itself occupies 4 bytes in length.
The concept that the pointer itself occupies memory is very useful in judging whether the pointer expression is a left value.
Arithmetic operation of pointer
The pointer can add and subtract integers. The significance of this operation of the pointer is different from the usual numerical addition and subtraction. For example:
Example 2:
1、chara[20];
2、int * ptr = a;
...
...
3、ptr++;
In the above example, the type of pointer ptr is int*, and the type it points to is int, which is initialized to point to integer variable A. In the next third sentence, pointer ptr is added with 1. The compiler handles this as follows: it adds the value of pointer ptr to sizeof(int), and in a 32-bit program, it is added with 4. Because the address is in bytes, the address pointed by ptr is increased by 4 bytes from the original address of variable A to the high address direction.
Because the length of char type is one byte, ptr originally refers to four bytes starting from cell 0 of array A, and now points to four bytes starting from cell 4 in array A. ..
We can use pointers and loops to traverse the array. See example:
Example 3:
intarray[20];
int * ptr = array
...
//The code for assigning values to integer arrays is omitted here.
...
for(I = 0; I & lt20; i++)
{
(* ptr)++;
ptr++;
}
This example adds 1 to the value of each cell in an integer array. Since the pointer ptr adds 1 in each loop, the next cell of the array can be accessed in each loop.
Look at this example again:
Example 4:
1、chara[20];
2、int * ptr = a;
...
...
3、ptr+= 5;
In this example, ptr is added with 5, and the compiler handles it like this: add 5 to the value of pointer ptr and multiply it by sizeof(int), which is 5 times 4=20 in a 32-bit program. Because the unit of address is bytes, the address pointed by the current ptr is 20 bytes higher than that pointed by ptr plus 5. In this example, ptr points to the first four bytes of cell 0 of array A before adding 5. After adding 5, ptr has pointed out the legal range of array A ... Although this situation will cause problems in application, it is grammatically possible. This also shows the flexibility of the pointer.
If in the above example, ptr is reduced by 5, then the process is similar, except that the value of ptr is reduced by 5 times sizeof(int), and the address pointed by the new ptr will be moved 20 bytes lower than that pointed by the original ptr.
To sum up, after adding an integer n to the pointer ptrold, the result is a new pointer ptrnew, the type of ptrnew is the same as that of ptrold, and the type of ptrnew is the same as that of ptrold. The value of ptrnew will be increased by n times of sizeof (the type that ptrold points to) bytes than the value of sizeof(ptrold). That is to say, the memory area pointed by ptrnew will move N times of size of (ptrold type pointed by ptrold) bytes in the high address direction than the memory area pointed by PTR old.
The result of subtracting the integer n from the pointer ptrold is a new pointer ptrnew, whose type is the same as that of ptrold, and the type pointed by ptrnew is also the same as that pointed by ptrold. The value of ptrnew will be reduced by n times of sizeof (the type of ptrold pointing) bytes than that of ptr old, that is to say, the memory area pointed by ptrnew will be moved to the lower address direction by n times of sizeof (the type of ptr old pointing) bytes.
Operator &; And *
This is an address operator, and * is ... what the book calls an indirect operator.
The operation result of & ampA is a pointer, the type of pointer is the type of A plus a *, the type of pointer is the type of A, and the address of pointer is the address of A. ..
*p's operation results are varied. In short, the result of *p is pointed by p, which has these characteristics: its type is the type pointed by p, and the address it occupies is the address pointed by p.
Example 5:
inta = 12;
intb
int * p;
int * * ptr
p = & ampa;
//& amp; The result of a is a pointer, the type is int*, the pointing type is int, and the pointing address is the address of a.
* p = 24
The result of //*p, here its type is int, and the address it occupies is the address pointed by P. Obviously, *p is the variable A.
ptr = & ampp;
//& amp; The result of p is a pointer whose type is p plus a *, and here is int **. The pointer points to the type of p, here is int*. The address pointed by the pointer is the address of the pointer p itself.
* ptr = & ampb;
//*ptr is a pointer, and the result of&b is also a pointer. The types of these two pointers are the same as those they point to, so it is no problem to assign a value to *ptr with & ampb.
* * ptr = 34
//* The result of PTR is what PTR points to, in this case, a pointer. If you do * operation on this pointer again, the result is a variable of type int.
Pointer expression
If the final result of an expression is a pointer, then the expression is called a pointer table.
Here are some examples of pointer expressions:
Example 6:
inta,b;
intarray[ 10];
int * pa
pa = & ampa; //& amp; Is a pointer expression.
int * * ptr = & amppa; //& amp; Pa is also a pointer expression.
* ptr = & ampb; //*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, it 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.
Because the result of pointer expression is a pointer, pointer expression also has four elements of pointer: the type of pointer, the type of pointer, the memory area pointed by pointer, and the memory occupied by pointer itself.
Well, when the result pointer of a pointer expression obviously has the memory occupied by 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 explicit memory. *ptr is a left value, because the pointer *ptr has occupied memory. In fact, *ptr is the pointer pa. Since pa has its own place in memory, *ptr certainly has its own place.
The relationship between arrays and pointers
If you don't quite understand the statement declaring an array, please refer to the article I posted some time ago:>.
The array name of an array can actually be regarded as a pointer. Please look at the following example:
Example 8:
intarray[ 10]=,value
...
...
value = array[0]; //can also be written as: value = * array.
value = array[3]; //can also be written as: value = * (array+3);
value = array[4]; //can also be written as: value = * (array+4);
In the above example, generally speaking, the array name array represents the array itself, and the type is int[ 10], but if array is regarded as a pointer, it points to the 0th cell of the array, and the type it points to is the type of the array cell, that is, int. So it's not surprising that *array equals 0. Similarly, array+3 is a pointer to the third cell of the array, so *(array+3) is equal to 3. Others and so on.
Example 9:
char*str[3]={
"Hello, thisisasample!" ,
"Hi, good morning." ,
“Helloworld”
};
chars[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 above example, str is a three-cell array, and each cell of the array is a pointer, and each pointer points to a string. If the pointer array name str is regarded as a pointer, it points to the 0th cell of the array, with the type of char** and the type of pointing to char*.
*str is also a pointer, the type is char*, the type it points to is char, and the address it points to is the string "Hello, thisisasample!" The address of the first character, that is, the address of' h'. Str+ 1 is also a pointer to the cell 1 of the array. Its type is char**, and the type it points to is char*.
*(str+ 1) is also a pointer, its type is char*, the type it points to is char, and it points to the first character' h' of "Hi, goodmorning". ",and so on.
Let's summarize the array name problem of arrays. If an array TYPEarray[n] is declared, the array name array has two meanings: one is to represent the whole array, and the type is type [n]; The second is a pointer, the TYPE of which is TYPE*, and the type of which the pointer points to is type, that is, the type of the array unit. The memory area pointed by the pointer is array cell 0, which occupies a separate memory area. Note that it is different from the storage area occupied by array cell 0. The value of the pointer cannot be modified, that is, the expression array++ is wrong.
The array name array can play different roles in different expressions.
In the expression sizeof(array), the array name array represents the array itself, so the sizeof function measures the size of the whole array.
In the expression *array, array acts as a pointer, so the result of this expression is the value of cell 0 of the array. Sizeof(*array) measures the size of array cells.
The expression array +n (where n = 0, 1, 2, ...) is a pointer, so the result of array +n is a pointer, its TYPE is TYPE*, the type it points to is type, and it points to the nth cell of the array. So sizeof(array+n) measures the size of pointer types.
Example 10:
intarray[ 10];
int(* ptr)[ 10];
Ptr = & array;
In the above example, ptr is a pointer whose type is int(*)[ 10], and the type it points to is int[ 10]. We initialize it with the first address of the whole array. In the statement ptr = &;; In array, array represents the array itself.
This section mentioned the sizeof () function, so let me ask, does sizeof (pointer name) measure the size of the pointer's own type or the size of the type pointed by the pointer? The answer is the former. For example:
int(* ptr)[ 10];
So 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, not the size of any other type.
Relationship between pointer and structure type
You can declare a pointer to an object of structural type.
Example 1 1:
structure
{
inta
intb
intc
}
my structs =;
//Declare the structure object ss, and initialize the three members of ss to 20, 30 and 40.
MyStruct * ptr = & ampss;
//Declare a pointer to the structure object ss. Its type is MyTruth *, and the type it points to is MyTruth.
int * pstr =(int *)& amp; ss;
//Declare a pointer to the structure object ss. But its type and the type it points to are different from ptr.
How to access three member variables of ss through pointer ptr?
Answer:
ptr-& gt; a;
ptr-& gt; b;
ptr-& gt; c;
How to access three member variables of ss through pointer pstr?
Answer:
* pstr// visited member A of ss.
*(pstr+ 1); //visited ss member B.
*(pstr+2)// Visit member C of ss.
Although I adjusted the above code in my MSVC++6.0, you should know that it is not normal to access structure members with pstr. To explain why it is not normal, let's look at how to access each cell of the array through a pointer:
Example 12:
int array[3]=;
int * pa = array
The method of accessing three cells of the array through the pointer pa is:
* pa// visited unit 0.
*(pa+ 1); //visited units 1.
*(pa+2); //visited unit 2.
From the format point of view, it is the same as the informal method of accessing structure members through pointers.
All C/C++ compilers always store array units in a continuous storage area when arranging array units, and there is no gap between the units. However, when storing members of a structure object, in a certain compilation environment, word alignment or double-word alignment or other alignment methods may be needed, and several "padding bytes" need to be added between two adjacent members, which may lead to a gap of several bytes between members.
Therefore, in the example 12, even if *pstr accesses the first member variable A of the structure object ss, there is no guarantee that *(pstr+ 1) will definitely access the structure member B. Because there may be some padding bytes between the member A and the member B, maybe *(pstr+ 1) only accesses these padding bytes. This also proves the flexibility of the pointer. If your goal is to see if there are padding bytes between structure members, hey, this is a good idea.
The correct way to access structure members through pointers should be to use the pointer ptr as in example 12.
Relationship between pointer and function
You can declare pointers as pointers to functions.
intfun 1(char*,int);
int(*pfun 1)(char*,int);
pfun 1 = fun 1;
....
....
inta=(*pfun 1)("abcdefg ",7); //Call the function through the function pointer.
You can use a pointer as a formal parameter of a function. In a function call statement, you can use a pointer expression as a parameter.
Example 13:
int fun(char *);
inta
charstr[]= " abcdefghijklmn ";
a = fun(str);
...
...
intfun(char*s)
{
int num = 0;
for(inti = 0; I {
num+= * s; s++;
}
returnnum
}
The fun function in this example calculates the sum of the ASCII code values of each character in the string. As mentioned earlier, the name of the array is also a pointer. In the function call, when str is passed to S as an argument, the value of str is actually passed to S, and the address pointed by S is the same as that pointed by str, except that str and S occupy their own storage space. Adding S 1 to the function body does not mean adding str 1 at the same time.
Pointer type conversion
When we initialize a pointer or assign a value to a pointer, there is a pointer to the left of the assignment number and a pointer expression to the right of the assignment number. In our previous example, in most cases, the type of pointer is the same as that of pointer expression, and the type pointed by pointer is the same as that pointed by pointer expression.
Example 14:
1、float TF = 12.3;
float * fptr = & ampf;
3、int * p;
In the above example, what should I do if I want the pointer P to point to the real number F? Is it in the following sentence?
p = & ampf;
Wrong. Because the pointer p is of type int*, it points to type int. Expression &; The result of f is a pointer of type float*, which points to the type float. The two are inconsistent, and the method of direct assignment is unacceptable. At least on my MSVC++6.0, the pointer assignment statement requires that both sides of the assignment number have the same type and point to the same type. I haven't tried it on other compilers. You can try it. In order to achieve our goal, we need to "cast":
p =(int *)& amp; f;
If there is a pointer p, we need to change its type and the type it points to to TYEP*TYPE, then the syntax format is:
(TYPE *)p;
The result of this forced TYPE conversion is a new pointer, its type is TYPE*, the type it points to is type, and the address it points to is the address pointed to by the original pointer. And all the properties of the original pointer p have not been modified.
If a function uses a pointer as a formal parameter, pointer type conversion will also occur in the process of combining the actual parameter and formal parameter of the function call statement.
Example 15:
void fun(char *);
inta= 125,b;
fun((char *)& amp; a);
...
...
Voidfun (number of characters)
{
charc
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 accounts for four bytes and the char type accounts for one byte. The funfunction is to reverse the order of four bytes of an integer. Have you noticed? In the function call statement, the parameter &; The result of a is a pointer, its type is int*, and the type it points to is int. The type of the parameter pointer is char*, and the type it points to is char. In this way, in the process of combining real parameters with formal parameters, it is necessary to convert from int* type to char* type. Combined with this example, we can imagine the process of conversion by the compiler: the compiler first constructs a temporary pointer char*temp, and then executes temp = (char *)&; A, finally pass the temp value to S, so the final result is: the type of S is char*, the type it points to is char, and the address it points to is the first address of A.
We already know that the value of the pointer is the address that the pointer points to. In a 32-bit program, the value of the pointer is actually a 32-bit integer. Can an integer be directly assigned to a pointer as the value of the pointer? Just like the following statement:
unsignedinta
*ptr type; //type is int, char or structure type, etc.
...
...
a = 20345686
Ptr = 20345686// Our purpose is to let the pointer PTR point to the address 20345686 (decimal
)
ptr = a; //Our purpose is to let the pointer ptr point to the address 20345686 (decimal).
Compile it. It turns out that the last two statements are wrong. So we can't achieve our goal? No, there's another way:
unsignedinta
*ptr type; //type is int, char or structure type, etc.
...
...
A= a number, which must represent a legal address;
ptr =(TYPE *)a; //Hehe, that will do.
Strictly speaking, (TYPE*) here is not the same as (TYPE*) in pointer type conversion. The (TYPE*) here means that the value of the unsigned integer a is regarded as an address. The above emphasizes that the value of a must represent a legal address, otherwise, when you use ptr, there will be illegal operation errors.
Think about whether the address pointed by the pointer, that is, the value of the pointer, can be taken out as an integer. Absolutely. The following example demonstrates how to take the value of a pointer as an integer and then assign the integer as an address to the pointer:
Example 16:
inta= 123,b;
int * ptr = & ampa;
char * str
b =(int)ptr; //Take the value of pointer ptr as an integer.
str =(char *)b; //Assign the value of this integer as the address to the pointer str.
Now we know that the pointer value can be taken out as an integer, or the integer value can be assigned to the pointer as an address.
The security problem of pointer
Please look at the following example:
Example 17:
chars = ' a
int * ptr
ptr =(int *)& amp; s;
* ptr = 1298;
The pointer ptr is a pointer of type int*, and the type it points to is int. The address it points to is the first address of S. In a 32-bit program, S occupies one byte and int type occupies four bytes. The last sentence not only changes one byte occupied by S, but also changes three bytes in the high address direction adjacent to S. What are these three bytes for? Only the compiler knows, and the person who writes the program is unlikely to know. Maybe these three bytes store very important data, maybe these three bytes are just a code of the program, and the values of these three bytes have been changed because of your careless application of the pointer! This will cause a crash error.
Let's look at another example:
Example 18:
1、chara
int * ptr = & ampa;
...
...
3、ptr++;
4 、* ptr = 1 15;
This example can be compiled and executed. But see? In the third sentence, after the pointer ptr is added with 1, ptr points to the storage area in the high address direction adjacent to the plastic variable A ... What is in this storage area? We don't know. It may be a very important data, or even a code. And the fourth sentence actually wrote a data into this storage area! This is a serious mistake. So when using pointers, programmers must be very clear in their hearts: where does my pointer point? When accessing an array with a pointer, you should also be careful not to exceed the low-end and high-end boundaries of the array, otherwise similar errors will occur.
In the forced type conversion of pointers: ptr 1=(TYPE*)ptr 2, if sizeof (type of ptr2) is greater than sizeof (type of ptr 1), it is safe to access the storage area pointed by ptr2 with the pointer ptr1. If sizeof (the type of ptr2) is less than sizeof (the type of ptr 1), it is unsafe to access the storage area pointed by ptr1.
2008 Baidu