Concept interpretation of C + + pointers [Super detail]

Source: Internet
Author: User

Transferred from: http://www.codeceo.com/article/cpp-pointer.html
A pointer is a special variable, and the value stored in it is 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.

Let's declare a few pointers for example:

Example one:

int *ptr;  char *ptr;  int **ptr;  int (*ptr)[3];  int *(*ptr)[4];
Type of 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:

int//指针的类型是int *  char//指针的类型是char *  int//指针的类型是 int **  int (*ptr)[3//指针的类型是 int(*)[3]  int *(*ptr)[4//指针的类型是 int *(*)[4]

What do you think? Is it easy to find out the type of pointers?

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:

int//指针所指向的类型是int  char//指针所指向的的类型是char  int//指针所指向的的类型是 int *  int (*ptr)[3//指针所指向的的类型是 int()[3]  int *(*ptr)[4//指针所指向的的类型是 int *()[4]

In the arithmetic operation of a 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.

The value of the pointer

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?

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.

Arithmetic operations of pointers

The pointer can add or subtract an integer. The meaning of this operation of the pointer is not the same as that of the usual numerical subtraction operation. For example:
Example two:

char a[20];   int *ptr=a;  ...  ...   ptr++;

In the example above, the type of the pointer ptr is int*, and the type it points to is 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 through an array, looking at an example:
Example three:

intarray[20];  int *ptr=array;  ...  //此处略去为整型数组赋值的代码。  ...  for(i=0;i<20;i++)  {      (*ptr)++;      ptr++;  }

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 at the example:

Example four:

char a[20];  int *ptr = a;  ...  ...  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.

Operators & and *

Here & is the take address operator, is ... The book is called the "indirect operator." The result of &a is a pointer, the type of the pointer is the type of a, the pointer is the type of a, the pointer points 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:

int a=12;  int b;  int *p;  int **ptr;  p=&a;//&a的结果是一个指针,类型是int*,指向的类型是int,指向的地址是a的地址。  *p=24;//*p的结果,在这里它的类型是int,它所占用的地址是p所指向的地址,显然,*p就是变量a。ptr=&p;//&p的结果是个指针,该指针的类型是p的类型加个*,在这里是int**。该指针所指向的类型是p的类型,这里是int*。该指针所指向的地址就是指针p自己的地址。 *ptr=&b;//*ptr是个指针,&b的结果也是个指针,且这两个指针的类型和所指向的类型是一样的,所以?amp;b来给*ptr赋值就是毫无问题的了。**ptr=34;//*ptr的结果是ptr所指向的东西,在这里是一个指针,对这个指针再做一次*运算,结果就是一个int类型的变量。指针表达式

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;  intarray[10];  int *pa;  pa=&a;//&a是一个指针表达式。  int **ptr=&pa;//&pa也是一个指针表达式。  *ptr=&b;//*ptr和&b都是指针表达式。  pa=array;  pa++;//这也是指针表达式。

Example VII:

char *arr[20];  char **parr=arr;//如果把arr看作指针的话,arr也是指针表达式  char *str;  str=*parr;//*parr是指针表达式  str=*(parr+1);//*(parr+1)是指针表达式  str=*(parr+2);//*(parr+2)是指针表达式

Because the result of a pointer expression is a pointer, the pointer expression also has four features that the pointer has: the type of 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, &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.

The relationship between arrays and pointers

If you don't understand the statement that declares an array, see the article I posted earlier << how to understand complex type declarations >> for C and C + +. The array name of an array can actually be seen as a pointer. Look at 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 typically represents the array itself, and the type is int [10], but if you think of array as a pointer, it points to the No. 0 cell of the array, the type is int, and the type that is the array cell is the type 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]);//也可写成strcpy(s,*str);  strcpy(s,str[1]);//也可写成strcpy(s,*(str+1));  strcpy(s,str[2]);//也可写成strcpy(s,*(str+2));

In the above example, STR is an array of three cells, each of which is a pointer 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 char, and the address it points to is a 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, which is of type char, and 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*, the type of the pointer is type, that is, the types of the array cells, The memory area that the pointer points to is the No. 0 unit 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:

intarray[10];  int (*ptr)[10];  ptr=&array;

In the example above, PTR is a pointer with the type int (*) [10], and the type he points to is int [10], and we initialize it with the first address of the entire array. In the statement
In 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 are:

sizeof(int(*)[10])==4  sizeof(int [10])==40  sizeof(ptr)==4

In fact, sizeof (the object) measured the size of the object's own type, not the size of any other type.

Relationship of pointers and struct types

You can declare a pointer to a struct type object.

Example 11:

struct MyStruct  {  int a;  int b;  int c;  }  MyStruct ss={20,30,40};//声明了结构对象ss,并把ss的三个成员初始化为20,30和40。MyStruct *ptr=&ss;//声明了一个指向结构对象ss的指针。它的类型是MyStruct*,它指向的类型是MyStruct。int *pstr=(int*)&ss;//声明了一个指向结构对象ss的指针。但是它的类型和它指向的类型和ptr是不同的。

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;//访问了ss的成员a。  *(pstr+1);//访问了ss的成员b。  *(pstr+2)//访问了ss的成员c。

Oh, although I msvc++6.0 over the above code in my own, but to know that it is not normal to use PSTR to access struct members, in order to explain why it is not normal, let us see how to access the array of cells through pointers:
Example 12:

intarray[3]={35,56,37};  int *pa=array;

The method by which the pointer PA accesses the array of three cells is:

*pa;//访问了第0号单元  *(pa+1);//访问了第1号单元  *(pa+2);//访问了第2号单元

The format is the same as the format of 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 (pstr+1) that the struct member B will be accessible. 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.

The relationship between pointers and functions

A pointer can be declared as a pointer to a function.

int fun1(char*,int);  int (*pfun1)(char*,int);  pfun1=fun1;  ....  ....  int a=(*pfun1)("abcdefg",7);//通过函数指针调用函数。

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.

Concept interpretation of C + + pointers [Super detail]

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.