"Turn" C language: pointer, C's soul

Source: Internet
Author: User

A total of eight chapters content. The first chapter. The pointer's conceptual pointer is a special variable that stores values that are interpreted as an address in memory. To make sense of a pointer, you need to be aware of the four aspects of the pointer: the type of pointer, the type that the pointer points to, the value of the pointer, the memory area that the pointer points to, and the memory area occupied by the pointer itself. Let's explain separately. First, we declare a few pointers for example: (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 post I posted in the previous period << How to understand complex type declarations >> for C and C + +. 1. The type of the pointer. From a grammatical point of view, you simply remove the pointer name from the pointer declaration statement, and the remainder is the type of the pointer. This is the type that the pointer itself has. Let's look at the types of pointers in example one: (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]? Is it easy to find out the type of pointers? 2. The type that the pointer points to. When you use a pointer to access the memory area pointed to by the pointer, the type that the pointer points to determines what the compiler will look for in that memory area. Syntactically, you only have to remove the pointer name and the pointer to the left of the name in the pointer declaration, and all that remains is the type that the pointer points to. For example: (1) int *ptr; The type that the pointer points to is int (2) char *ptr; The type that the pointer points to is char (3) int **ptr; The type that the pointer points to is int * (4) int (*PTR) [3]; The type that the pointer points to is int () [3] (5) int * (*PTR) [4]; The type that the pointer points to is int * () [4] in the arithmetic operation of the pointer, the type that the pointer points to has a great effect. The type of the pointer (that is, the type of the pointer itself) and the type that the pointer points to are two concepts. As you become more familiar with C, you will find that the concept of "type", which is mixed with pointers, is divided into "types of pointers" and "types pointed to by pointers", which is one of the key points of mastery of pointers. I read a lot of books, found that some poorly written books, the pointer to the two concepts stirred together, so look at the contradiction between the book, the more confused look. 3.The value of the pointer, or the memory area or address to which the pointer is pointing. The value of the pointer is the value stored by the pointer itself, which is treated as an address by the compiler, not a generic value. In a 32-bit program, the value of all types of pointers is a 32-bit integer because the memory address in the 32-bit program is all 32 bits long. The memory area that the pointer points to is the memory address from which the value of the pointer is represented, and the length of the memory area of sizeof (the type the pointer is pointing to). Later, we say that the value of a pointer is XX, which is equivalent to saying that the pointer to an XX-led address of a piece of memory area; we say that a pointer points to a region of memory, which is equivalent to saying that the value of the pointer is the first address of the memory area. The memory area that the pointer points to and the type that the pointer points to are two completely different concepts. In example one, the pointer points to a type that already exists, but because the pointer is not initialized, the memory area it points to is nonexistent, or meaningless. Later, every time you encounter a pointer, you should ask: What is the type of this pointer? What type is the pointer pointing to? Where does the pointer point? 4. The memory area occupied by the pointer itself. How much memory does the pointer itself occupy? You just have to use the function sizeof (the type of the pointer) to find out. In a 32-bit platform, the pointer itself occupies a length of 4 bytes.  The concept of memory occupied by the pointer itself is useful when judging whether a pointer expression is an lvalue. Chapter Two. The pointer's arithmetic operation pointer can be added to or subtracted from an integer. The meaning of this operation of the pointer is not the same as that of the usual numerical subtraction operation. Example: Example two: 1. Char a[20];2. int *ptr=a; 3. ptr++; In the above example, the type of the pointer ptr is int*, and it points to an int, which is initialized to point to the shaping variable A. In the 3rd sentence, the pointer ptr is added 1, which is handled by the compiler: it adds the value of the pointer ptr to sizeof (int), and in the 32-bit program, it is added 4. Since the address is in bytes, the address pointed to by PTR is incremented by 4 bytes from the address of the original variable A to the high address direction. Since the length of the char type is one byte, the original ptr is the four bytes starting at Unit No. 0 of array A, pointing to the four bytes from array a starting at unit 4th. We can use a pointer and a loop to iterate over an array, looking at an example: example three: int Array[20];int *ptr=array;...//The code that assigns values to an integer array is omitted here. ... for (i=0;i<20;i++) {(*ptr) + +;p tr++;} This example adds 1 to the value of each cell in an integer array. Because each loop has a pointer ptr plus 1, each loop has access to the next cell of the array. Look again Example: Example four: 1。 Char a[20];2. int *ptr=a; 3. ptr+=5; In this example, PTR is added with 5, and the compiler handles this by adding the value of the pointer ptr to 5 by sizeof (int), which adds 5 times 4=20 to the 32-bit program. Because the unit of the address is byte, the current PTR points to an address that is 20 bytes to the high address direction than the address pointed to by PTR after 5. In this example, PTR, which is not added to 5, points to the four bytes starting at Unit No. 0 of array A, plus 5, and PTR points to the legal range of array A. Although this situation may be problematic in application, it is syntactically possible. This also shows the flexibility of the pointer. If PTR is subtracted by 5 in the example above, then the process is much the same, except that the value of PTR is subtracted by 5 by sizeof (int), and the new PTR points to an address that moves 20 bytes to the lower address direction than the address pointed to by the original PTR. Summing up, after a pointer ptrold plus an integer n, the result is a new pointer ptrnew,ptrnew of the same type as the Ptrold, and the same type that ptrnew points to and the type that ptrold points to. The value of ptrnew will increase by N by sizeof (the type that the Ptrold points to) by more than the value of Ptrold. That is, the memory area pointed to by Ptrnew will move n by sizeof (the type that the Ptrold points to) bytes than the memory area pointed to by Ptrold to the high address direction. After a pointer ptrold minus an integer n, the result is a new pointer ptrnew,ptrnew of the same type as the Ptrold, and the same type that ptrnew points to and the type that ptrold points to. The value of ptrnew will be less than the value of Ptrold by sizeof (the type that the Ptrold points to) bytes, that is, the memory area that the ptrnew points to will move n by sizeof (the type that the Ptrold points to) than the memory area pointed to by Ptrold A byte. Chapter Three. Operators & and * Here & is the fetch address operator, * is ... The book is called the "indirect operator." The result of the &a operation is a pointer, the type of the pointer is a type of a, a pointer to the type of a, the pointer to the address, that is the address of a. The result of *p's operation is very multifarious. In short *p The result is what P points to, this thing has these characteristics: its type is the type of P, which occupies the address that P points to. Example five: The result of an int a=12;int b;int *p;int **ptr;p=&a;//&a is a pointer, the type is int*, the type that points to is int, and the address that points to is the address of a. *p=24;//*p the result, where its type is int, and it occupies the address that P points to, it is clear that *p is the variable A. The result of the ptr=&p;//&p is a pointer, the type of the pointer is the type of P plus a *, here is the int**. The type that the pointer points to is the type of P, which is int*. The address that the pointer points to is the pointer P's own address. *ptr=&b;//*ptr is a pointer, and the result of &b is also a pointer, and the two pointers are of the same type as the one they are pointing to, so the amp;b to assign to *ptr is no problem. The result of the **ptr=34;//*ptr is what PTR points to, and here is a pointer to do another * operation on the pointer, and the result is a variable of type int. Fourth chapter. Pointer expression. The final result of an expression if it is a pointer, then the expression is called the pointer expression. Here are some examples of pointer expressions: Example VI: int a,b;int array[10];int *pa;pa=&a;//&a is a pointer expression. int **PTR=&AMP;PA;//&AMP;PA is also a pointer expression. Both *ptr=&b;//*ptr and &b are pointer expressions. pa=array;pa++;//This is also an expression of pointers. Example VII: Char *arr[20];char **parr=arr;//If you think of arr as a pointer, arr is also a pointer expression char *str;str=*parr;//*parr is a pointer expression str=* (parr+1);//* (Parr +1) is the pointer expression str=* (parr+2);//* (parr+2) is a pointer expression because the result of the pointer expression is a pointer, so the pointer expression also has four features that the pointer has: the type of the pointer, the type that the pointer points to, the memory area that the pointer is pointing to, and the memory that the pointer itself occupies. Well, when the result pointer of a pointer expression has explicitly had the memory occupied by the pointer itself, the pointer expression is an lvalue, otherwise it is not an lvalue. In example VII, &AMP;A is not an lvalue because it does not yet occupy a definite amount of memory. *ptr is an lvalue, because *ptr this pointer has occupied the memory, in fact *ptr is the pointer PA, since PA has in memory has its own position, then *ptr of course also has its own position. Fifth chapter. Array and pointer relationships if you don't understand the statement that declares an array, see the article I posted earlier << how to understand complex type sounds for C and C + +Ming >>. The array name of an array can actually be seen as a pointer. See the following example: Example VIII: INT array[10]={0,1,2,3,4,5,6,7,8,9},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, the array name array is typically the array itself, and the type is int [10], but if you think of array as a pointer , which points to the No. 0 cell of the array, the type is int *, and the type that is pointed to is the type of the array cell, which is int. So it's not surprising that *array equals 0. Similarly, array+3 is a pointer to the 3rd cell of the array, so * (array+3) equals 3. Other and so forth. Example nine: Char *str[3]={"Hello,this is a sample!", "Hi,good morning.", "Hello World"};char s[80];strcpy (s,str[0]);//can also be written as strcpy (S,*STR); strcpy (s,str[1]);//may also be written as strcpy (s,* (str+1)); strcpy (s,str[2));//may also be written as strcpy (s,* (str+2)); In the above example, STR is an array of three units, Each cell of the array is a pointer that points to a string. With the pointer array name STR as a pointer, it points to the No. 0 element of the array, which is of type char**, and it points to a type of char *. *STR is also a pointer to the type char*, which is the type of char, and it points to the address of the string "Hello,this is a sample!" The address of the first character, which is the address of ' H '. Str+1 is also a pointer to the 1th element of the array, whose type is char**, which is the type of char *. * (str+1) is also a pointer, its type is char*, it points to a type of char, which points to "Hi,good morning." The first character ' H ', and so on. The following summarizes the problem with array names for arrays. Declares an array of type array[n], the array name arrays has two meanings: first, it represents the entire array, it is of type [n]; second, it is a pointer, the type of the pointer is type*, and the pointer is a type, that is, a numberThe type of the group cell, which points to the memory area that is the No. 0 cell of the array, which occupies a separate memory area, noting that it is different from the memory area occupied by the group No. 0 unit. The value of the pointer cannot be modified, that is, an expression like array++ is wrong. Array names in different expressions can play different roles. In the expression sizeof (array), array name arrays represent the array itself, so the sizeof function detects 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 cell number No. 0. sizeof (*array) measured the size of the array element. Expression array+n (where n=0,1,2, ...). ), array acts as a pointer, so the result of Array+n is a pointer, which is of type type*, and it points to the type, which points to the array nth unit. So sizeof (ARRAY+N) measured the size of the pointer type. Example ten: int array[10];int (*PTR) [x];p tr=&array; in the example above, PTR is a pointer, its type is int (*) [10], the type he points to is int [10], and we initialize it with the first address of the entire array. In statement Ptr=&array, array represents the array itself. The function sizeof () is mentioned in this section, so let me ask, does sizeof (the pointer name) measure the size of the pointer itself, or the size of the type that the pointer points to? The answer is the former. For example: Int (*ptr) [10]; In a 32-bit program, there is: sizeof (int (*) []) ==4sizeof (int []) ==40sizeof (PTR) ==4 in fact, sizeof (object) It is measured by the size of the object's own type, not by any other type. Sixth chapter. The relationship of pointers and struct types can declare a pointer to a struct type object. Example 11: struct mystruct{int a;int b;int c;} MyStruct ss={20,30,40};//declares the struct object SS and initializes the three members of the SS to 20,30 and 40. MyStruct *ptr=&ss;//declares a pointer to the struct object ss. Its type is mystruct*, and the type it points to is mystruct. int *pstr= (int*) &ss;//declares a pointer to the struct object ss. But its type and the type it points to and PTR are different. How can I access the three member variables of SS through pointer ptr? Answer:ptr->a;ptr->b;ptr->c; How can I access the three member variables of SS through pointer pstr? Answer: *pstr;//visited member a of SS. * (pstr+1);//access member of SS B. * (pstr+2)//visited member of SS C. Oh, although I msvc++6.0 over the above code, but to know that using PSTR to access the structure members is not normal, in order to explain why the irregular, let us see how to access the array of cells through pointers: example 12: int array[3]={ 35,56,37};int *pa=array; Access to the array of three cells through the pointer Pa method is: *pa;//access to Unit No. 0 * (pa+1);//access to Unit 1th * (pa+2);// The access to unit 2nd is the same format as the informal method of accessing struct members through pointers. All the C + + compilers, when arranging cells in an array, always store each array cell in a contiguous storage area, with no gaps between the cells and the cells. However, when you store individual members of a structure object, in a certain compilation environment, you may need to align the words or the two words or something else, and you need to add several "padding bytes" between the adjacent two members, which results in a possible number of bytes of space between the members. Therefore, in example 12, even if *PSTR accesses the first member variable A of the struct object SS, there is no guarantee that * (PSTR+1) will have access to struct member B. Because there may be several padding bytes between member A and member B, it is possible that * (PSTR+1) has access to these padding bytes. This also proves the flexibility of the pointer. If your goal is to see if there are any padding bytes between the members of each structure, hey, that's a good idea. The correct way to access struct members through pointers should be to use the pointer ptr method in example 12. Seventh chapter. The relationship between pointers and functions can declare a pointer as a pointer to a function. int fun1 (char*,int), int (*pfun1) (char*,int);p fun1=fun1;........int a= (*pfun1) ("ABCDEFG", 7);//functions are called through function pointers. You can use a pointer as a parameter to a function. In a function call statement, you can use a pointer expression as an argument. Example 13: int Fun (char*), int a;char str[]= "ABCDEFGHIJKLMN"; A=fun (str); int fun (char*s) {int num=0;for (int i=0;i< Strlen (s); i++) {num+=*s;s++;} return num;} The function fun in this example counts the sum of the ASCII values of each character in a string. As I said earlier, the name of the array is also a pointer. In a function call, when the STR is passed to the parameter s as an argument, the value of STR is actually passed to the address that the s,s points to, but Str and s each occupy their respective storage space. The self-adding 1 operation of S in the function body does not imply that STR is also self-added to the 1 operation. Eighth chapter. Pointer type conversion When we initialize a pointer or assign a value to a pointer, the left side of the assignment number is a pointer, and the right side of the assignment number is a pointer expression. In the example above, in most cases, the type of the pointer is the same as the type of the pointer expression, and the pointer points to the same type as the pointer expression. Example 14:1. Float f=12.3;2. Float *fptr=&f;3. int *p; In the above example, what if we want the pointer p to point to the real f? Is it using the following statement? p=&f; wrong. Because the type of pointer P is int*, the type it points to is int. The result of the expression &f is a pointer, the type of the pointer is float*, and the type it points to is float. There is no inconsistency between the two, the direct assignment method is not possible. At least on my msvc++6.0, the assignment statement for the pointer requires the same type on both sides of the assignment, and the same type, and the other compiler I haven't tried, you can try. In order to achieve our goal, "forced type conversion" is required: p= (int*) &f; If there is a pointer p, we need to change its type and the type it is pointing to tyep* and type, then the syntax format is: (type*) p; So the result of coercion type conversion is a new pointer , the type of the new pointer is type*, and it points to a type that is the address that the original pointer points to. All the properties of the original pointer p have not been modified. A function if a pointer is used as a formal parameter, the conversion of the pointer type occurs during the combination of the arguments and the parameters of the function call statement. Example 15: void Fun (char*), int a=125,b;fun ((char*) &a), ... 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 takes up four bytes, and the char type takes up one byte. The function of fun is to reverse the order of four bytes of an integer. NoteDoes that mean it? In a function call statement, the result of the amp;a is a pointer, which is of type int *, and it points to an int. The type of the pointer for the parameter is char*, which is the type of char. Thus, in the combination of arguments and parameters, we must perform a conversion from the int* type to the char* type. With this example, we can imagine the compiler's process of converting: The compiler constructs a temporary pointer char*temp, then executes temp= (char*) &a, and finally passes the value of temp to S. So the final result is that the type of S is char*, which is the type of char, and the address it points to is the first address of a. 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 actually a 32-bit integer. Would it be possible to assign an integer to the pointer directly as a value of the pointer? Just like the following statement: unsigned int A; Type *ptr;//type is a int,char or struct type, and so on. ... a=20345686;ptr=20345686;//our goal is to make the pointer ptr point to address 20345686 (decimal) ptr=a;//Our goal is to make the pointer ptr point to address 20345686 (decimal) compile it. It turns out that the last two statements are all wrong. So we're not going to be able to achieve this? No, there are ways: unsigned int A; Type *ptr;//type is a int,char or struct type, and so on. ... a= a number, this number must represent a valid address; Ptr= (type*) a;//Oh, that's it. Strictly speaking, the (type*) and pointer type conversions (type*) are not the same. Here (type*) means to treat the value of unsigned integer a as an address. It is emphasized that the value of a must represent a valid address, otherwise an illegal operation error occurs when you use PTR. Think about the reverse, take the pointer to the address that the pointer value as an integer to take out. It's perfectly possible. The following example shows the value of a pointer being taken as an integer and then assigning the integer as an address to a pointer: example 16: int a=123,b;int *ptr=&a;char *str;b= (int) ptr;// Take the value of the pointer ptr as an integer. Str= (char*) b;//assigns the value of this integer to the pointer str as an address. Well, now that we know, you can take the value of the pointer as an integer, or you can assign an integer value as an address to a pointer. Nineth Chapter. Pointers to security issues look at the followingExample: Example 17: Char s= ' a '; int *ptr;ptr= (int*) &s;*ptr=1298; pointer ptr is a pointer to a int* type that points to the type int. The address it points to is the first address of S. In a 32-bit program, S occupies one byte and the int type occupies four bytes. The last statement changes not only the one byte that s occupies, but also the three bytes of the high address direction that is adjacent to S. What are these three bytes for? Only the compiler knows, and the person who writes the program is less likely to know. Perhaps these three bytes store very important data, perhaps these three bytes is exactly a code of the program, and because of your sloppy application of the pointer, the value of this three bytes has been changed! This can cause a crash error. Let's look at one more example: Example 18:1. Char a;2. int *ptr=&a; 3. Ptr++;4. *ptr=115; This example is fully compiled and can be executed. But did you see it? The 3rd sentence after the pointer ptr self-add 1 operation, PTR points to the shape variable a adjacent to the high address direction of a block of storage. What's in this storage area? We don't know. It is possible that it is a very important piece of data, possibly even a code. And the 4th sentence actually writes a piece of data to this storage area! This is a serious mistake. So when using pointers, the programmer must be very clear: where my pointer is pointing. When accessing an array with pointers, be careful not to go beyond the lower and upper bounds of the array, or it will cause similar errors. In the coercion type conversion of pointers: ptr1= (type*) ptr2, if sizeof (the type of PTR2) is greater than sizeof (the type of PTR1), it is safe to use the pointer ptr1 to access the store that the ptr2 points to. If sizeof (the type of PTR2) is less than sizeof (the type of PTR1), it is unsafe to use the pointer ptr1 to access the store that the ptr2 points to. As for why, the reader combined with an example Shilai think, should understand. Please write out the results of the following program: [Img]http://images.blogcn.comude<stdio.h>int *p;pp (int a,int *b); main () {int a=1,b=2,c=3;p=& B;PP (a+c,&b);p rintf ("(1)%d%d%dn", a,b,*p);} PP (int a,int *b) {int c=4;*p=*b+c;a=*p-c;printf ("(2)%d%d%dn", a,*b,*p);}

"Turn" C language: pointer, C's soul

Related Article

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.