[C Language] Learning of pointers, addresses, and references

Source: Internet
Author: User

1. Multiplication Operator  2. Define pointersInt * p = 0; or int * p = 0 ;? The latter is easier to understand: defines a Variable P, which is pointer-type (more detailed, it is pointer-type pointing to int, the previous definition seems to define the strange thing * P. However, the next write method will bring about an easy misunderstanding: int * P1, P2; here it seems to be the definition of two pointer variables P1 and P2. However, in fact, this intuition is wrong. The correct understanding is int * P1, P2; that is, P1 is pointer type, while P2 is indeed Integer type. In Ms VC ++ 6.0, it is written in the following format. 3. What is a pointer?Is the pointer only a memory address? Also, note that when we define pointers, they are all associated with a type, such as int, Char, or string. If the pointer only represents an address in the memory, so why are there so many changes associated? DWORD p = 0; to solve the problem. What is the purpose of the associated data type? It instructs the compiler how to explain the memory content on a specific address and how many memory units the memory area should span. For example, int * P. the compiler can obtain information from this definition: 1. P points to the memory that stores integer data. 2. Because only one data is stored in the memory area, the memory area is 4 bytes, that is, the effect of p + 1 is to skip four bytes. Another complex example, for example, struct a {int x1; short X2; A * Next;} defines the pointer A * P. What does the compiler explain this pointer? 1. P points to the memory area and stores three types of data in sequence: int, short, and pointer-type data. 2. P points to the memory area that spans 12 bytes. That is, p + 1 skips 12 bytes. (Why not 10? Reason for alignment) However, C ++ defines a special pointer to explain the content and size of the memory area in general pointers to meet specific needs, for example, we only need the first address of a block of memory and do not need to consider the data type and size. This form is void *; a pointer of this type can be assigned a value to a pointer of any data type, such as type A * above, void * q = P; the only exception is, you cannot assign a function pointer to it. 4. Const ModifierWhen the const encounters a pointer, It is troublesome to see: const int * P; int * const P; const int * const P; the first expression indicates that p is a pointer, P itself is very ordinary, but P points to a special object-an integer constant; the second represents: This P pointer is not a common pointer, it is a constant pointer, that is to say, you can only initialize it, but cannot assign values. In addition, the object pointed to by this pointer is an ordinary int type variable. The third is combined with the first two: pointers and pointing objects are both constants. With const, the assignment problem becomes troublesome. First, for const int * P; here, Because P points to a constant, so when you reference this object through P, you cannot assign a value to it! A constant object cannot be pointed to by a common pointer, but must be pointed to a constant. The reason is very simple. A normal pointer can be used to change the value pointed, but can a non-constant object, that is, a common variable, assign its address to a pointer pointing to a constant? Yes, but once it points this way, since the pointer itself defines a pointer to a constant, the compiler considers it to point to a variable, therefore, you cannot use this pointer to modify the object value. Second, for int * const P; here P itself is a constant pointer, so it cannot be assigned at all, so there is no problem with the assignment. You cannot use constants to initialize them, because the pointer does not point to constants. You can only use variables to initialize them. Third, for const int * const P; here, it can only be initialized and cannot be assigned a value. You can use constants for initialization or variables for initialization, but you cannot use the pointer to assign values to the variables. Const int * P, a pointer to a constant object, is often used as the form parameter of some functions. It is intended to prevent the parameter modifications that will be passed in the function from the compiler's perspective, although the user can avoid it, it is more reliable-when the user accidentally modifies the real parameter behavior, the compiler discovers and blocks this behavior. This pointer is of the const XX * const type. 5. Functions and pointersPointer to a function: You can use it to call a function instead of a function name. How to define a function pointer. Because a program can use multiple functions with the same name (that is, function overloading), when defining a function pointer, it must contain function parameters, in this way, the pointer can be pointed to a function accurately. Definition: int (* p) (const char *, INT); indicates that p is a pointer to the function. The two parameters of this function are const char * and Int, in addition, this function returns an int value. Confusing: int * P (const char *, INT); a bracket is missing. In this case, the compiler interprets int * P (const char *, INT ); that is, it indicates a function declaration. The function name is P, and a pointer pointing to the int type is returned. Int * (* p) (const char *, INT); defines a function pointer P, which points to a function, the two parameters of this function are const char * and int. This function returns a pointer to the int type. Function pointer initialization and initialization: The function name is like an array name. The Compiler interprets it as a pointer to this type of function. Therefore, you can use the function name, or & function name to initialize or assign values to the function pointer. In addition, you can use another function pointer to initialize and assign values to the pointer. The important thing is the pointer and function name. The pointer and pointer must have the same parameter table and return type (they must be the same, but none of them can be used ). There is no implicit type conversion. You must ensure full consistency. Initialize or assign a value of 0, indicating that it does not point to any function. Using the function pointer to call a function can be called like p (x, y) or * p (x, y), provided that P has been correctly assigned or initialized. Function return pointer: A non-basic type object can be returned. 6. arrays and pointersInt A [3] = {1, 2, 3}; Consider the meanings of the expressions a, a [0], & A, and & A [0: first, the values of the three expressions are the same -- the first address of the array (the address of the first 0th elements in the array), but the compiler has different interpretations of the three: For, the compiler interprets it as a pointer pointing to an integer data, so a + 1 points to the first element in the array, and a + 2 points to the second element. The pointer A has some special properties: A is not a common pointer. It is also an array name, that is, it is associated with an array. Therefore, some properties are different from normal pointers. A normal pointer can be assigned a value, that is, you can use one address or another pointer to modify the pointer of the current pointer. However, for a pointer associated with an array, if this assignment is allowed, therefore, elements in the array cannot be accessed. Therefore, the pointer represented by the array name cannot be assigned a value. At this point, a is a pointer constant, that is, it can only be initialized and cannot be assigned a value.   Although a cannot be assigned a value, it is completely possible to assign a to other elements, which is no different from normal pointers.In summary, a is equivalent to a pointer constant. (Type * const type) Essentially, the [I] operation is interpreted by the compiler as * (a + I) operation, that is, the [] operator is implemented through the array name pointer, therefore, the meaning of & A [0] Is & (* A). Obviously, the pointer is first * (unreferenced) and then & (referenced), which is equivalent to nothing, the pointer itself, so a is completely equivalent to & A [O], -- (& A [0]) [I] is equivalent to a [I], and the form is a bit strange. For the expression & A, it is strange that this is also the first address of the array, that is, the first address of this array contains a pointer constant (that is, the array name ), but isn't the first address of the array containing an int-type number? What's going on? Can an address store two things? It cannot be explained at the moment. It can be thought that the compiler will return the first address of the array when it finds this combined operation with the array name. However, this is only a pure address, it no longer has the pointer feature, that is, the compiler no longer interprets it as a pointer, and users cannot access the next array element through the + 1 operation. The plus 1 is the plus 1 in mathematics. What happens when the array becomes multi-dimensional? Consider the two-dimensional array int B [4] [3] = {1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {10, 11, 12}; B, meanings of several expressions in & B, B [0], & B [0], & B [0] [0]: first, in C ++, array elements are stored in the row order, that is, the first row of data is stored in the first row, and the second row of data is stored in the second row ,...., so. First, consider array name B. The Compiler also interprets array name B as a pointer, but obviously this pointer is not a common pointer. This B points to the first address of all elements in the array, which is beyond doubt. How much memory does this pointer span in one step? In this example, B spans 12 bytes in one step, that is, B spans a row of elements in the array. In fact, B is a pointer, or a pointer to a pointer, that is, B points to a pointer (also for B + 1, B + 2), B [I] [J]. This access method is essentially through + I, jump the pointer to row I to obtain the pointer B [I] pointing to the first address of row I. Then, jump to step J through + J, reaches the J element, that is, find the elements of the I row and column J. So B is the pointer, and B [I] is the pointer. Here, B [I] is similar to a in one dimension. What about & B? & B is still the first address of the array, but similar to the one-dimensional one, it is a pure address and no longer has the pointer feature. Its + 1 is the mathematical + 1, you cannot use + 1 to access the next element. Similarly, after the & B [I], & operator is added, B [I], which is originally a pointer, is denied as a pointer and returns a pure address. In fact, because [] is essentially a reference to the pointer, we can access the array elements without the [I] [J] method, you can do this: (* (a + I) [J], * (a [I] + J), or * (a + I) + J ), these methods are equivalent. What about & B [I] [J? Let's change B [I] [J] into * (B + I) + J), which makes it easy to understand the problem, the original * B [I] [J] is equivalent to & (* (B + I) + J). We can remove the outer brackets, it becomes * (B + I) + J, that is, B [I] + J. Obviously, this is a pointer pointing to the elements of row I and column J, this pointer is interpreted as a data that spans an int type at a time. Let's be more abnormal. Consider the 3D situation. Although the 3D array is rare, consider it. After all, the space coordinates are represented by 3D. Int C [2] [3] [4] = {1, 2, 3}, {5, 6, 7, 8}, {9, 10, 11, 12 },{ 13, 14, 15, 16 }, {17,18, 19,20}, {, 22, }}; first, the array name c. the compiler interprets C as a pointer pointing to the first address of the array. Because the row order is the primary order, therefore, this pointer spans 12 integers in a total of 48 bytes, which actually spans a two-dimensional array. For & C, similar to the one-dimensional and two-dimensional scenario, is it a pure address. C [I? It can be inferred that C [I] is similar to B in two dimensions, that is, a pointer to a pointer. C [I] spans 4 integers and 16 bytes in one step. C [I] is the pointer to the pointer, so c is the pointer to the pointer (dizzy ~). C [I] is also equivalent to * (C + I). As for C [I] [J], this is the true int pointer, that is, the pointer to the real data, each step spans an int type and 4 bytes. Similar to two-dimensional expressions, for & C [I] [J], the compiler returns an address. Although it is the same as the value of C [I] [J], it is only a pure address, the Unit is a byte. For C [I] [J] [K], no nonsense. Is this an address for & C [I] [J] [k? Is this a pointer? We still need to use another representation of []: C [I] [J] [k] is equivalent to * (C + I) + J) + k), then & C [I] [J] [k] is equivalent to * (C + I) + J) + K, that is, C [I] [J] + K, that is, the pointer to the (I, j, k) element, one step across the unit into an int type. Let's take a look at how to find the elements (I, j, k: 1. c [I] [J] [k] 2. * (C [I] [J] + k) 3. * (C [I] + J) + k) 4, * (C + I) + J) + k) 5, (* (C + I )) [J] [k] 6. (* (C + I) + J) [k] 7. * (C + I )) [J] + k) 8. (* (C [I] + J) [k] can be seen. There are eight writing methods in total. In fact, there are three solutions for reference, select [] or *. In this way, there are a total of 8 combinations. (There are four types of two dimensions and two types of one dimension) 7. typedef and pointerTypedef seems very simple, such as typedef int integer; however, these simple typedef statements are easy to misunderstand, and typedef is a macro replacement, replace the following custom type with the previous known type. Is that true? Apparently not! Consider the following question: how to define a pointer type pointing to an integer type? How to define a function pointer type? The first problem is very simple: typedef int * int_pointer; that seems to be less simple for the second problem. First, let's look at the function pointer definition method: int (* P) (const &, INT); The P point to the function must return int, and the form parameter must be const & and Int. Name the pointer type func_pointer as follows: typedef int (* func_pointer) (const &, INT); you can understand it as follows: typedef int integer; remove typedef, which is the definition of a variable. Here we define an int-type Integer. What type is this integer, the typedef statement defines Integer as this type. Remove typedef from typedef (* func_pointer) (const &, INT); to define a function pointer, that is, func_pointer is defined as a function pointer type variable, the original typedef defines func_pointer as the function pointer type. 8. Functions, arrays and pointersINT (* testcases [10]) (); what does this expression mean? The combination of pointers, arrays, and functions becomes complicated. It defines an array, testcases [10]. The elements in the array are function pointers, and the type of function pointers is int (*) (). How can we understand this definition? First, consider the definition of the array. The general definition mode of the array is: type array name [size]. Considering this expression, it seems that an array is defined, however, the array name [size] is clipped in the middle. What is the type? We found that the type is not a simple data type, but a function pointer type int (* p )(), this function has no parameter and returns the int type. Thus, this expression defines an array of function pointers with a size of 10. Typedef can be used to simplify this definition: typedef int (* PFV) (); PFV testcases [10]; In fact, INT (* testcases [10]) (); here we define a function pointer array, which is the subject. The following is a question: how to define a pointer to an array? The pointer to an array seems fresh. the pointer to an array is an array. In fact, we have already encountered a pointer to an array. For example, a two-dimensional array name is actually a pointer to an array. It spans a row of data at a time, which is actually a one-dimensional array, the 3D array name is also a pointer to an array. It spans a two-dimensional array composed of low dimensions at a time. Array pointer (pointer to array) Definition: int (* PTR) [3]; This expression defines an array pointer PTR, which spans a one-dimensional array consisting of three int types at a time. It is found that the definition method is very similar to the function pointer definition method, but the () is changed to [].Furthermore, if we want to define a pointer to an array, and the elements in the array are not simple int type, but complex types, how should we define it? In fact, array pointers are rare enough, and are never used in general programming. We only need to be able to read complicated things, you do not have to construct such complex types. Complex expressions:         1. INT (* P () []) () [];First, P is a function based on P (), and then a pointer is returned Based on the * sign before P, next, let's take a look at what class this Pointer Points to. We can replace * P () with * pointer, which is the pointer returned by function P, then it becomes int (* pointer) []) () []; then according to (* pointer) [], which indicates that the pointer is an array pointing, what is the element type in this array? Since the array name is actually a pointer, we replace (* pointer) [] (that is, (* P () []) with an array, in this way, it becomes int (* array) () []; it is found that array is a function pointer, so that every element in the array is a function pointer. What about this function, returns a pointer type. Replace (* array) () with func and it becomes an int.
(* Func) []; this indicates that the func function returns a pointer to the array, and the element in the array is int type. This expression is cool !!! 2. p = (INT (*) [20]) [10]) q; this is a forced type conversion. Q is forcibly converted into a pointer type, this pointer is a straight line of an array with 20 elements. The elements in this array are pointers to another array, which is a one-dimensional array containing 10 int data. It can be seen that when analyzing complex expressions (the so-called complex, that is, combining pointers, arrays, and functions, it will not be complicated if it is missing), starting from the innermost layer of brackets, the innermost layer is the "Root Node" of the complex expression, and then the layer-by-layer detachment is like this, for example, the layer-by-layer is an array, so what is the element of this array? It is the outer layer. If the layer is a function with a return value, what is the value returned by this function? That is, the outer layer, so that the expression can be parsed layer by layer.   There are some other things about typedef: typedef INT (* PFV) (); this defines a function pointer, so pfv p; can define a pointer to the function.Typedef int (* P [10]) (); this is to define P as a function pointer array, so P array; the statement can define an array of function pointers, the array name is array, which contains 10 elements. Typedef int (* parray) [3]; this defines a pointer to an integer array, so parray PTR; defines a pointer to an array. How do I assign values or initialize this PTR? In fact, the two-dimensional array name is used to assign values (initialize) to it, because the two-dimensional array name, as a pointer to the array, spans an array at a time. Typedef int A [3] [3]; what does this statement mean? This is to define a as a 3*3 integer array type. When a B = {1}, a 3 × 3 integer array is initialized. Similarly, a typedef int A [3]; this statement defines a as a one-dimensional array. Typedef Void func (INT); this statement defines a function type. Through this typedef, we can clearly define the function pointer, func * P.  Typedef char * string; const string STR; what type of STR is this Str? Const char * STR, which is the pointer type to a constant? In fact, the answer is incredible. STR is a constant pointer rather than a pointer constant, that is, the const modifier is for a pointer rather than a char. 9. References and pointersReferences are similar to pointer constants. They can only be initialized and cannot be assigned values. An alias (alias) is another name for reference. Objects can be manipulated indirectly through reference. Constant reference is similar to the constant pointer pointing to a constant. It is special to initialize a constant by using constants, variables, or even constants. If you use a variable to initialize constant reference, you cannot modify this variable through this reference, but the original variable name is acceptable. This is similar to assigning a variable address to a constant pointer. The constant pointer cannot be used to modify the variable, but its own variable name can be used. There can be pointer references, such as int A = 1; int * P = & A; int * & R = P; then r becomes the reference of pointer p. If it is const int * P = & A; it indicates that it is a constant pointer, so the definition of reference is as follows: const int * & R = P; this statement indicates that R is a pointer reference. This pointer is a pointer variable pointing to a constant, and does not mean that this reference is a constant reference. If this pointer is not only a constant pointer, but also a pointer constant, that is, const int * const P. when defining a reference, note that const int * const & R
= P; this indicates that the reference is a constant reference. Here is a problem when a variable address is used to initialize the reference, for example, int A = 22; int * const & pi_ref = & A; note that it should be regarded as a constant reference, because & A is not a variable name, it is similar to a constant. If const int A = 22; const int * const & pi_ref = & A; that is, the const in the middle is used to define constant reference, the previous const reflects that the referenced object (pointer) points to the const object. We have object names or object pointers, which can manipulate objects. Why should we introduce the reference concept? In fact, the most common reference is the form parameter used as a function. It is a good way to use references to manipulate an external object in a function. For reference, the reference can only be initialized and cannot be assigned a value. Because the initialized reference becomes the alias of the referenced object, and then assigned a value, it is not a value assignment to the reference itself, but a value assignment to the referenced object.

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.