Pointer in my eyes

zhaozj2021-02-17  56

This article is taken from the C language version of Netease Guangzhou Community. Author Girlrong is the previous C language version of the master, she is happy, honest, and is very welcomed by netizens. Unfortunately, it has been returned to the rivers and lakes. The author is the initiator service. This is my post. I am also an initiator (emphasizing countless times), I put it out with my understanding of the initiator. Due to the language of the primary school, the language is not necessarily to achieve this goal. Try to do our best. The pointers are difficulties and focuses in C and C . I only master the BASIC under DOS. Other various features of the C language, there are similar things in Basic. Only pointers are not available in Baisc. The pointer is the soul of C. I don't want to repeat most books, I just said that I just said that I have seen the books I have seen or not, and I think I understand something that I understand is a little. My purpose is: 1. Written by writing these things, clearing the blurred knowledge about C in my head. 2. Give beginners a little prompt. 3. Earn a few experience values. (Because it is suspected of sticking these things) first chapter. The concept pointer of the pointer is a special variable, which is interpreted as an address in the memory. To figure out a pointer, you need to figure out the four aspects of the pointer: the type of pointer, the type pointed to by the pointer, the value of the pointer or the memory area pointed to by the pointer, and the memory area occupied by the pointer itself. Let us explain separately. First declare several pointers to put the example: Example 1: (1) INT * PTR; (2) Char * PTR; (3) int ** PTR; (4) int (* ptr) [3]; (5) INT * (* PTR) [4]; If you don't understand a few examples, please refer to the article I posted for some time. "How to understand the complex type declaration of C and C >>. 1. Type of pointer. From a grammatical point of view, you only need to remove the pointer name in the statement statement, and the remaining part is the type of this pointer. This is the type of pointer itself. Let's take a look at the type of each pointer in Example: (1) INT * PTR; / / The type of pointer is int * (2) char * PTR; / / pointer type 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]; // pointer Type is int * (*) [4]? Is it very simple to find the type of a pointer? 2. The type pointed to the pointer. When you pass the pointer to access the memory area points to the pointer, the type pointed to by the pointer determines what the compiler will treat the content in the memory area. From the grammar, you only need to remove the pointer name and the pointer declare * on the left side of the name of the pointer statement. The remaining is the type pointed to by the pointer. For example: (1) INT * PTR; / / The type pointed to by the pointer is int (2) char * PTR; / / The type pointed to by the pointer is the CHAR (3) int ** PTR; / / pointer points to Type is int * (4) int (* ptr) [3]; / / The type pointed to by the pointer is int () [3] (5) INT * (* PTR) [4]; / ​​/ pointer points to The type is int * () [4] In the arithmetic operation of the pointer, the type pointed to by the pointer has a large role. The type of pointer (ie, the type of pointer itself) and the type pointed to by the pointer are two concepts. When you are more familiar with C, you will find that the "type" "type" of the pointer stir together is divided into "the type of pointer" and "the type pointed to the pointer", which is the key point of the proficiency pointer. one.

I have read a lot of books, I found some books that were poor, and the two concepts of the pointer were stirred together, so I looked at the conflict before and after, the more I saw it. 3. The value of the pointer or the memory area or address pointed to by the pointer. The value of the pointer is the value stored in the pointer itself, which will be used as an address by the compiler, not a general value. In a 32-bit program, all types of pointers are a 32-bit integer because the memory address is all 32-bit in the 32-bit program. The memory pointer points to the memory area begins with the memory address represented by the value of the pointer, a memory area of ​​the length of sizeof (the type pointed to by the pointer). In the future, we said that the value of a pointer is XX, which is equivalent to the memory area that is the address of XX as XX; we say that a pointer points to a block memory area, which is equivalent to this pointer is this The first address of the memory area. The type of memory pointed to the pointer and pointer is two completely different concepts. In the example one, the type pointed to by the pointer is already, but since the pointer has not been initialized, the memory area indicted to it does not exist, or meaningless. In the future, every time a pointer should ask: What is the type of this pointer? What is the type pointing to the pointer? Where does this pointer point to? 4. The memory area occupied by the pointer itself. How much memory itself does the pointer itself? You only need to use a function Sizeof (type of pointer) to know. In the 32-bit platform, the pointer itself occupies 4 bytes of length. The concept of the memory itself is useful when it is determined whether a pointer expression is a left value. Chapter two. The arithmetic operation pointer of the pointer can be added or minus an integer. The meaning of this operation of the pointer and the meaning of the usual value of the usual value are different. Example: Example 2: 1. CHAR A [20]; 2. INT * PTR = a; ... 3. PTR ; In the above example, the type of pointer PTR is int *, which point points to INT, which is initialized to point to the shaping variable A. In the next article 3, the pointer PTR is added 1, the compiler is processed: it adds the value of the pointer PTR with SIZEOF (int), in the 32-bit program, is added 4. Since the address is in units, the address pointed to by the PTR increases by 4 bytes from the address of the original variable A. Since the length of the CHAR type is one byte, the original PTR is four bytes that point to No. 0 unit of array A. At this point, at this point, at this point, at this point, at this point, the four bytes starting from the number 4 unit. We can use a pointer and a loop to traverse an array, see example: INT Array [20]; int * ptr = array; ... // This will be omitted to the code of the integer assignment. ... for (i = 0; i <20; i ) {(* PTR) ; PTR ;} This example adds the value of each unit in the integer array 1. Since each loop is plugged in 1, the next unit of the array can be accessed each time a loop. Look at the example: Example 4: 1. CHAR A [20]; 2. INT * PTR = a; ... 3. PTR = 5; In this example, PTR is added 5, the compiler is processed: adding the value of the pointer PTR plus 5 by sizeof (int), in the 32-bit program plus 5 multiplication 4 = 20. Since the unit of the address is byte, the address pointed to by the current PTR moves 20 bytes to the high address direction than the address pointed to the PTR after adding 5.

In this example, it is not added to the four bytes starting from the PTR before 5, and the PTR has pointed to the legal range of the array A. Although this situation will have problems in the application, but it is possible in grammar. This also reflects the flexibility of the pointer. If in the previous example, PTR is subtracted 5, then the processing process is similar, but the value of the PTR is subtracted to be subjected to 5 multiply SizeOf (int), the new PTR pointing is lower than the address pointed to by the original PTR. The address direction moves 20 bytes. Summarize, after a pointer Ptrold adds an integer N, the result is a new pointer PTRNEW, the type of PTRNEW and the type of Ptrold, the type pointed to by PtrNew and the type pointed to by Ptrold. The value of the PTRNEW will add N-multiply SIZEOF (Type of Ptrold) by the value of Ptrold. That is to say, the memory area pointed to by PTRNEW moves n-multiply SIZEOF (Type of Ptrold) by the memory area pointed to by Ptrold. After a pointer Ptrold subtracts an integer N, the result is a new pointer PTRNEW, the type of PTRNEW and the type of PTROLD. The type pointed to by PtrNew and the type pointed to by Ptrold. The value of PTRNEW will reduce N-multiply size and the value of the N multiply sizeof (Type of Ptrold) by the value of Ptrold, that is, the memory area pointed to by PtrNew will move n-by-multiply SIZEOF in the memory area pointed to by PTROLD. (Type pointed to Ptrolt) byte. third chapter. Operators & and * Here & It is to take the address operator, * is ... The book is called "indirect operator". The calculation result of & a is a pointer, the type of pointer is a type of A *, the type pointed to by the pointer is the type of A, the address pointed to by the pointer, that is, the address of A. * P The calculation result is a five-flowers. In short, the result is something pointed to P, this feature: It is the type of P pointing, and its address is the address pointed to by P. Example 5: INT A = 12; int b; int * p; int ** PTR; P = & a; // & a result is a pointer, the type is int *, the point to the type is int, the pointing address is A address. * P = 24; // * P results, here it is int, the address it occupies is the address pointed to by P, apparent, * p is the variable A. PTR = & P; // & p The result is a pointer, the type of the pointer is the type P, which is added *, here is int **. The type pointed to this pointer is the type of P, which is int *. The address points to the pointer is the address of the pointer P. * Ptr = & b; // * Ptr is a pointer, and the result of & B is also a pointer, and the type of these two pointers is the same, so use & b to give * PTR assignment is no problem. ** PTR = 34; // * PTR's result is something pointed to by PTR, here is a pointer, and then doing the pointer again * calculation, the result is a Int type variable. Chapter Four. Pointer expression. The last result of an expression If it is a pointer, then this expression is called a pointer expression. Here 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 both a pointer expression. 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 due to pointer expressions The pointer expression also has four elements of the pointer: the type of pointer, the type pointed to by the pointer, the memory area pointed to by the pointer, the memory itself occupies. Ok, when a pointer expression results pointer have explicitly have the memory itself, this pointer expression is a left value, otherwise it is not a left value. In Example 7, & A is not a left value because it has not yet occupied a clear memory. * PTR is a left value, because * PTR This pointer has occupied memory, in fact, * PTR is a pointer PA, since PA has already had its own position in memory, then * PTR has its own position. chapter Five. The relationship between arrays and pointers do not understand the statement of the declaration array, please refer to the article I posted for some time. << How to understand the complex type of C and C >>. The array name of the array is actually as a pointer. Look at the example: Example 8: int Array [10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, value; ... ... value = array [0]; // can also be written: value = * array; value = array [3]; // can also be written: value = * (array 3); value = array [4]; // can also be written: value = * Array 4); in the previous example, the general two group name array represents the array itself, the type is int [10], but if Array is as a pointer, it points to the 0th unit of the array, the type is int *, The type of point is the type of array unit, int. So * Array is not surprising. Similarly, Array 3 is a pointer to the third unit of array, so * (array 3) is equal to 3. Others are so pushing. Example 9: CHAR * STR [3] = {"Hello, this is a name!", "Hi, Good Morning.", "Hello World"}; char s [80]; STRCPY (S, Str [0]) ; // can also be written as STRCPY (S, * STR); STRCPY (S, STR [1]); // can also be written into STRCPY (S, * (STR 1)); STRCPY (S, STR [2]) ; // can also be written as STRCPY (S, * (STR 2)); in the above example, STR is an array of three units, and each unit of the array is a pointer, which points to a string. That a pointer is used as a pointer, it points to the number 0 unit of the array, its type is char **, which is a type of char *.

* STR is also a pointer, its type is char *, the type it is pointing is char, which pointing the address is the first character of the string "Hello, this is a sample!", 'h' address. Str 1 is also a pointer, pointing to No. 1 unit of array, its type is char **, which is a type of char *. * (STR 1) is also a pointer, its type is char *, which is the type that is char, which points to "Hi, Good Morning." First characters 'h', and so on. The following is summarized below the number of group names of the array. Declare an array type array [n], then array name Array has two meanings: First, it represents the entire array, its type is type [n]; second, it is a pointer, the type of the pointer Is Type *, the type of pointer is Type, which is the type of array unit. The memory area points to which the pointer points is an array No. 0 unit, which accounts for a separate memory area, pay attention to it and the array No. 0 unit The memory area is different. The value of the pointer cannot be modified, ie the expression like Array is wrong. ARRAY can play different roles in different expressions in different expressions. In the expression sizeof (array), the array name array represents an array itself, so the sizeOf function measured the size of the entire array at this time. In the expression * array, Array plays a pointer, so the result of this expression is the value of the array No. 0 unit. SizeOf (* array) is measured by the size of the array unit. Expression Array N (where n = 0, 1, 2, .....), Array plays a pointer, so the result of Array N is a pointer, its type is type *, it points to the type It is TYPE, which points to the array N number unit. Therefore, SizeOf (Array N) is measured by the size of the pointer type. Example 10: Int Array [10]; int (* ptr) [10]; PTR = & array; upper example PTR is a pointer, its type is int (*) [10], the type he point to INT [10 ], We initialize it with the first address of the entire array. In the statement PTR = & Array, Array represents an array itself. In this section, the function sizeof () is mentioned, then I will ask questions, the SIZEOF (pointer name) is measured by the size of the pointer itself or the size of the type pointed to by the pointer? The answer is the former. For example: int (* ptr) [10]; in the 32-bit program, there is: sizeof (int (*) [10]) == 4 sizeof (int [10]) == 40 sizeof (PTR) == 4 In fact, SizeOf (object) is measured by the size of the object itself, rather than any other type of size. Chapter Six. The relationship between pointers and structural types can declare a pointer to the structural type object. Example 11: struct mystruct {int A; int b; int C;} mystruct ss = {20, 30, 40}; // Declare structure object SS, and initialize SS three members to 20, 30 and 40 .

MyStruct * ptr = & ss; // Declare a pointer to the structural object SS. Its type is mystruct *, which points to which is mystruct. INT * PSTR = (int *) & ss; // Declare a pointer to the structural object SS. But its type and the type and PTR it point to it are different. How do I access the three member variables of SS by pointer PTR? Answer: ptr-> a; ptr-> b; ptr-> c; how to access the three member variables of SS by pointer PSTR? Answer: * PSTR; // Access the member a of SS. * (PSTR 1); // Access the member B of SS. * (PSTR 2) // Access the member C of SS. Oh, although I have repel the above code in my MSVC 6.0, I have to know that I use PSTR to access structural membership is inquirable. In order to explain why I don't regular, let's see how to access arrays through the pointer. Each unit: Example 12: int Array [3] = {35, 56, 37}; int * pa = array; three units of the three units of array from the pointer PA are: * pa; // Access 0 Number * (PA 1); // Access the No. 1 unit * (PA 2); // Access the No. 2 unit from the format is the same as the format of the unflavible method of accessing the structure by the pointer . When all the C / C compilers are arranged in the array, the individual array units always store each array unit in a continuous storage area, and there is no gap between the unit and the unit. However, when the various members of the structural object, in some kind of compilation environment, it may need the word alignment or double word alignment or other alignment, need to add several "padding bytes" between adjacent two members. This leads to a number of bytes of voids between each member. So, in Example 12, even if the * PSTR accesses the first member variable A of the structural object SS, it is not guaranteed * (PSTR 1) will be able to access the structural member B. Because there may be some filling bytes between member a and members b, maybe * (PSTR 1) just visited these padding bytes. This also proves the flexibility of the pointer. If your purpose is to see if there is any fill byte between the members of each structure, hey, this is a good method. The correct way to access structural members through the pointer should be a method of using a pointer PTR in an example 12. Chapter VII. The relationship between the pointers and functions can declare a pointer into a pointer to a function. INT FUN1 (CHAR *, INT); int (* pfun1) (char *, int); pfun1 = fun1; .... .... Int a = (* PFUN1) ("Abcdefg", 7); ///// The function is called through the function of the function. The pointer can be used as a function of the 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

In the function call, after the STR is transmitted to the formation S, the value of the STR is passed to the address pointed to the STR, which is consistent with the address pointed to by the STR, but the STR and S are occupied. Storage space. The self-inclination of S in the function is not intended to be a self-adding 1 calculation on the STR. chapter eight. Pointer Type Conversion When we initialize a pointer or give 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 we mentioned earlier, in most cases, the type of pointer and the type of pointer expression is the same, the type pointed to the pointer and the type pointed to by the pointer expression. Example fourteen: 1. Float f = 12.3; 2. Float * fptr = & f; 3. INT * P; in the above example, if we want the pointer P to point to real num f, what should I do? Is it the following statement? P = & f; wrong. Because the type of pointer P is int *, the type it points to is int. The result of expression & f is a pointer, the type of pointer is float *, which point points to float. The two are inconsistent, and the method directly assigned is not. At least on my MSVC 6.0, the assignment of the assignment statement of the pointer requires the type of two sides, and the type pointed to the same is true. I haven't tried it on other compilers. Everyone can try it. In order to achieve our purpose, "Mandatory Type Conversion": P = (INT *) & F; If there is a pointer P, we need to change its type and the type of type to Tyep * and Type, then the syntax format is : (TYPE *) P; This is the result of the forced type conversion is a new pointer. The type of the new pointer is type *. It points to the type, which is the address pointing to the original pointer. And all attributes of the original pointer P have not been modified. A function If the pointer is used as a ginseng, the pointer type conversion will occur during the combination of the actual parametric and metall parameters of the function call statement. Event 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 accounts for four bytes, and the char type accounts for one byte. The function of function FUN is to reverse the order of the four bytes of an integer. Do you notice? In the function call statement, the result of the active argument & a is a pointer, its type is int *, which point points to INT. The type of parameter this pointer is char *, which is the type of CHAR. Thus, during the binding process of the arctic and meticulum, we must conduct a conversion from int * type to char * type. Combined with this example, we can imagine the process of transformation of the compiler: The compiler first constructs a temporary pointer char * TEMP, then execute Temp = (char *) & A, and finally passing the value of TEMP to S. So the final result is: the type of S is char *, which is the type of char, which is the first address of A. We already know that the value of the pointer is the address pointed to by the pointer. In the 32-bit program, the value of the pointer is actually a 32-bit integer.

Can you assign an integer as a value of the pointer to the pointer? Just like the following statement: unsigned int a; type * ptr; // type is int, char or structural type, and the like. ... a = 20345686; PTR = 20345686; // Our purpose is to make the pointer PTR point to address 20345686 (decimal) PTR = a; // Our purpose is to point the pointer PTR to address 20345686 (decimal) Compile it. It was found that the following two statements were all wrong. So can't our purpose you have? No, there is also a way: unsigned int a; type * ptr; // Type is int, char or structural types and so on. ... a = a number, this number must represent a legal address; PTR = (Type *) a; // Oh, this is OK. Strictly speaking (Type *) and pointer type conversion (Type *) is still different. Here (Type *) means that the value of the unsigned integer A is treated as an address. The above emphasizes that the value of A must represent an legitimate address. Otherwise, if you use PTR, illegal operational errors will occur. Think of that you can't turn it, the value of the pointer to the pointer is taken out as an integer. absolutely okay. The following example demonstrates the value of a pointer as an integer, then put this 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; // Put the value of this integer as an address to the pointer STR. Ok, now we already know, you can take the value of the pointer as an integer, or you can use an integer value as an address to a pointer. Chapter nine. Pointer Safety Problem See the example below: CHAR S = 'a'; int * ptr; ptr = (int *) & s; * ptr = 1298; pointer PTR is an int * type pointer, it points to The type is int. The address it points to is the first address of S. In the 32-bit program, s is one byte, and the int type is four bytes. The last statement not only changed one byte of S, but also changes the three bytes of the high address direction from S. What is these three bytes do? Only the compiler knows that the writer is unlikely. Perhaps these three bytes have a very important data, perhaps these three bytes are just a code of the program, and because of your horses and tiger applications, these three bytes are changed! This causes crash errors. Let's take another example: Eighteen: 1. CHAR A; 2. INT * PTR = & a; ... 3. PTR ; 4. * PTR = 115; this example can be compiled and can be executed. But did you see? The third sentence is used to perform the self-inclination of the pointer PTR, and the PTR points to a storage area in the high address direction adjacent to the plastic variable A. What is this storage area? we do not know. It is possible that it is a very important data, and may even be a code. The fourth sentence actually writes a data in this storage area! This is a serious mistake. So when using a pointer, the programmer must be very clear: Where is my pointer pointing?

转载请注明原文地址:https://www.9cbs.com/read-30725.html

New Post(0)