Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Detailed explanation of relevant knowledge points of C pointer

2025-03-28 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article introduces the relevant knowledge of "detailed explanation of C pointer-related knowledge points". In the operation of actual cases, many people will encounter such a dilemma, so let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!

Preface: complex type description

To understand pointers, there will be some more complex types, so let me first introduce how to fully understand a complex type. It is actually very simple to understand a complex type. There are many operators in a type. Like ordinary expressions, they also have priority, and their priority is the same as that of operation, so I summed up the principle: starting from the variable name, combining according to operator priority. Analyze step by step. Let's start with a simple type and analyze it slowly:

Int p; / / this is a common integer variable int * p; / / starts from P and combines with * first, so P is a pointer, and then combined with int, indicating that the type of content pointed to by the pointer is int. So P is a pointer int p [3] that returns integer data; / / it starts at P and combines it with [] to show that P is an array, and then combines with int to show that the elements in the array are integer, so P is an array composed of integer data int * p [3]. / / first, start from P and combine with []. Because its priority is higher than *, P is an array, and then it is combined with * to show that the elements in the array are of pointer type, and then combined with int to show that the type of content pointed to by the pointer is integer, so P is an array int (* p) [3] consisting of pointers that return integer data. / / first, starting from P, combine with * to show that P is a pointer and then combine with [] (with "()" this step can be ignored, just to change the priority), indicating that the content pointed to by the pointer is an array, and then combined with int to show that the elements in the array are integer. So P is a pointer int * * p to an array of integer data; / / first, starting with P, combining with *, saying that P is a pointer, and then combining with *, indicating that the element pointed to by the pointer is a pointer, and then combining with int, indicating that the element pointed to by the pointer is integer data. Since secondary pointers and more advanced pointers are rarely used in complex types, we will not consider multi-level pointers for later more complex types, but only one-level pointers at most. Int p (int) / / from P, first combine with () to show that P is a function, and then enter the analysis in () to show that the function has a parameter of an integer variable, and then combine it with the external int, indicating that the return value of the function is an integer data Int (* p) (int). / / starting from P, it is first combined with the pointer to indicate that P is a pointer, and then combined with () to indicate that the pointer points to a function, and then combined with the int in () to indicate that the function has a parameter of int type, and then combined with the outermost int, indicating that the return type of the function is an integer. So P is a pointer int * (* p (int)) [3] to a function that has an integer parameter and returns an integer type. / / you can skip it first, without looking at this type. If it is too complicated, start with P, combine with (), show that P is a function, then enter (), combine with int, show that the function has an integer variable parameter, and then combine with the outer *, indicating that the function returns a pointer, and then go to the outermost layer and combine it with [] first to show that the returned pointer points to an array. Then combine with * to show that the elements in the array are pointers, and then combine with int to show that the pointer points to integer data. So P is a function whose argument is an integer and returns a pointer variable that points to an array of integer pointer variables.

That's about it. That's all we have to do. After understanding these types, other types are also a piece of cake for us, but we generally don't use too complex types, which will greatly reduce the readability of the program. Please use it with caution, the above types are enough for us.

I. elaborate on the pointer

A pointer is a special variable in which the value stored is interpreted as an address in memory. To figure out a pointer, you need to understand four aspects of the pointer: the type of the pointer, the type the pointer points to, the value of the pointer or the area of memory that the pointer points to, and the area of memory occupied by the pointer itself. Let's explain separately.

First 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]

1. Type of pointer

From a grammatical point of view, you just need to remove the pointer name from the pointer declaration statement, and the rest is the type of pointer. This is the type of pointer itself. Let's look at the types of pointers in example 1:

(1) the type of int*ptr;// pointer is int* (2) the type of char*ptr;// pointer is char* (3) the type of int**ptr;// 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?

two。 The type that the pointer points to

When you use a pointer to access the area of memory that the pointer points to, the type the pointer points to determines what the compiler will think of the contents of that area of memory.

Syntactically, you only need to remove the pointer name in the pointer declaration statement and the pointer declaration * to the left of the name, and all that is left is the type that the pointer points to. For example:

(1) the type pointed to by the int*ptr; / / pointer is int (2) the type pointed by the char*ptr; / / pointer is char (3) the type pointed to by the int**ptr; / / pointer is int* (4) int (* ptr) [3]; / / the type pointed to by the pointer is int () [3] (5) int* (* ptr) [4]; / / the type pointed to by the pointer is int* () [4]

The type that the pointer points to plays an important role in the arithmetic operation of the pointer.

The type of the pointer (that is, the type of the pointer itself) and the type the pointer points to are two concepts. As you become more and more familiar with C, you will find that dividing the concept of "type" mixed with pointers into "types of pointers" and "types of pointers" is one of the key points for mastering pointers. I read a lot of books and found that in some poorly written books, the two concepts of the pointer were mixed together, so I became more and more confused when I read the book.

3. 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 by the pointer itself, and this value will be treated by the compiler as an address rather than a normal value. In 32-bit programs, the value of all types of pointers is a 32-bit integer, because memory addresses in 32-bit programs are all 32 bits long. The area of memory that the pointer points to is a piece of memory whose length is si zeof (the type the pointer points to), starting from the memory address represented by the value of the pointer. Later, when we say that the value of a pointer is XX, it is equivalent to saying that the pointer points to a memory area headed by XX; when we say that a pointer points to a memory area, it means that the value of the pointer is the first address of that 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 1, the type that the pointer points to already exists, but because the pointer has not been initialized, the area of memory it points to does not exist, or is meaningless.

In the future, every time you encounter a pointer, you should ask: what is the type of this pointer? What is the type of pointer? Where does the pointer point? (key note)

4 the memory area occupied by the pointer itself

How much memory does the pointer itself take up? You only need to test it with the function sizeof (the type of pointer). On a 32-bit platform, the pointer itself occupies a length of 4 bytes. The concept of memory occupied by the pointer itself is useful in determining whether a pointer expression (explained later) is a left value.

Second, the arithmetic operation of pointer

The pointer can add or subtract an integer. The meaning of this operation of the pointer is different from that of the usual numerical addition and subtraction, in units. For example:

Example 2:

Char a [20]; int * ptr= (int *) a; / / casting does not change the type ptr++ of a

In the above example, the pointer ptr is of type int*, and it points to type int, which is initialized to point to the integer variable a. In the next third sentence, the pointer ptr is added 1, and the compiler handles it like this: it adds sizeof (int) to the value of the pointer ptr, which is added 4 in 32-bit programs, because int takes up 4 bytes in 32-bit programs. Because the address is in bytes, the address pointed to by ptr is increased by 4 bytes from the address of the original variable a to the high address. Because the length of the char type is one byte, it turns out that ptr is the four bytes that point to the beginning of unit 0 of the array a, which now points to the four bytes of the array a starting from unit 4. We can iterate through an array with a pointer and a loop. Look at the example:

Example 3:

Int array [20] = {0}; int * ptr=array;for (iDefino ptr-; / / pointing to the operator, or (* ptr) .a, it is recommended that the former be used as ptr- > b TX PTR-> c

And how to access the three member variables of ss through the pointer pstr?

Answer:

* pstr; / / visited a member of ss. * (pstr+1); / / visited member b of ss. * (pstr+2) / / visited member c of ss.

Although I have called up the above code on my MSVC++6.0, you should know that it is irregular to use pstr to access structure members. To illustrate why it is irregular, let's look at how to access each unit of an array through a pointer: (change the structure to an array)

Example 13:

Int array [3] = {35 pa 56 pa=array;// 37}; the way int * pa=array;// accesses the three units of the array array through the pointer is: * pa; / / accessed Unit 0 * (pa+1); / / visited Unit 1 * (pa+2); / visited Unit 2

In terms of format, it is the same as the informal method of accessing structure members through pointers.

When arranging the cells of an array, all the C _. However, when storing the members of the structure object, in a certain compilation environment, word alignment or double-word alignment or some other alignment may be required, and several "padding bytes" need to be added between the two adjacent members. this results in a gap of several bytes between the members.

Therefore, in example 12, even if * pstr accesses the first member variable an of the structure object ss, there is no guarantee that * (pstr+1) will access structure member b. Because there may be several padding bytes between member an and member b, maybe * (pstr+1) happens to access these padding bytes. This also proves the flexibility of pointers. If your goal is to see if there are any padded bytes between the members of the structure, hey, that's a good idea.

However, the correct way for pointers to access structure members should be to use the pointer ptr in example 12.

The relationship between pointers and functions

You can declare a pointer as a pointer to a function.

Int fun1 (char *, int); int (* pfun1) (char *, int); pfun1=fun1;int a = (* pfun1) ("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 an argument.

Example 14:

Int fun (char *); inta;char str [] = "abcdefghijklmn"; a=fun (str); int fun (char * s) {int num=0; for (int iTunes;) {num+=*s;s++;} return num;}

The function fun in this example counts the sum of the ASCII code values of each character in a string. As mentioned earlier, the name of the array is also a pointer. In the function call, when str is passed to parameter s as an argument, the value of str is actually passed to the address pointed to by str, which is the same as that pointed to by str, but str and s each occupy their own storage space. The self-add-1 operation of s in the body of the function does not mean that the self-add-1 operation is performed on str at the same time.

VIII. Pointer type conversion

When we initialize a pointer or assign a value to a pointer, to the left of the assignment is a pointer, and to the right of the assignment is a pointer expression. In the previous example, in most cases, the type of the pointer is the same as that of the pointer expression, and the type that the pointer points to is the same as the type that the pointer expression points to.

Example 15:

Float fallow 12.3 float * fptr=&f;int * p

In the above example, what if we want the pointer p to point to the real number f?

Do you use the following sentence?

Pairvof

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 of type float *, which points to type float.

The two are inconsistent, and the method of direct assignment is not good. At least on my MSVC++6.0, the pointer assignment statement requires that the types on both sides of the assignment sign are the same and point to the same type. I haven't tried it on other compilers, so you can try it. In order to achieve our purpose, we need to do a "cast":

P = (int*) & 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 cast is a new pointer of type TYPE *, which points to type TYPE, which points to the address that the original pointer points to.

None of the properties of the original pointer p have been modified. (remember)

If a function uses a pointer as a formal parameter, the type must be consistent in the process of combining the argument and parameter of the function call statement, otherwise it needs to be cast.

Example 16:

Void fun (char*); int axiom 125 ((char*) & a); void fun (char*s) {charc; cymbals * (sphinx 3); * (sphinx 3) = * (sphinx 0); * (sphinx 0) = c; (sphinc2) = * (sphin1); * (sphin1) = 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 fun reverses the order of four bytes of an integer. Have you noticed? In a function call statement, the result of the argument & an is a pointer of type int * and a type of int. The type of the pointer is char *, and the type it points to is char. In this way, in the process of combining arguments with formal parameters, we must make a conversion from int * type to char * type.

Combined with this example, we can do this.

Imagine the conversion process of the compiler: the compiler first constructs a temporary pointer char * temp, then executes temp= (char *) & a, and finally passes the value of temp to s. So the end result is that the type of s is char *, it points to type 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 assigned directly to the pointer as the value of the pointer? Like the following statement:

Unsigned int a too type * ptr; / / TYPE is an int,char or structure type, and so on. / / our goal is to make the pointer ptr point to the address 20345686 ptr=a; / / our goal is to make the pointer ptr point to the address 20345686 ptr=a; / compile it. It turns out that the last two statements are all wrong. So our goal can't be achieved? No, there is another way: unsigned int a _ type * ptr; / / TYPE is an int,char or structural type, and so on. A proper N / / N must represent a legal address; ptr= (TYPE*) a; / / hehe, that's fine.

Strictly speaking, (TYPE *) here is not the same as (TYPE *) in pointer type conversion. Here (TYPE*) means to treat the value of an unsigned integer an as an address. It is emphasized above that the value of a must represent a legal address, otherwise there will be an illegal operation error when you use ptr. Think about whether you can reverse the address that the pointer points to, that is, the value of the pointer as an integer. Absolutely. The following example demonstrates taking the value of a pointer as an integer and then assigning the integer to a pointer as an address:

Example 17:

Int axiom 123 ptr; int * ptr=&a;char * str;b= (int) int / / takes 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.

Now we know that the value of the pointer can be taken as an integer, or an integer value can be assigned to a pointer as an address.

IX. Safety of pointers

Look at the following example:

Example 18:

Char swarms ptrackers * int * ptr;ptr= (int *) &

The pointer ptr is a pointer of type int *, which points to type int. The address it points to is the first address of s. In 32-bit programs, s takes up one byte and the int type takes up four bytes. The last statement changes not only one byte occupied by s, but also three bytes in the direction of the high address adjacent to s. What are these three bytes for? Only the compiler knows, but the person who wrote the program is unlikely to know. Maybe these three bytes store very important data, maybe these three bytes happen to be a piece of code of the program, and because of your careless use of pointers, the values of these three bytes have been changed! This can lead to collapsing mistakes.

Let's look at another example:

Example 19:

Char a _ int * ptr=&a;ptr++;*ptr=115

The example can be compiled and executed. But did you see that? In the third sentence, after adding 1 to the pointer ptr, ptr points to a memory area in the high address direction adjacent to the integer variable a. What's in this storage area? We don't know. It's possible that it's a very important piece of data, maybe even a piece of code.

And the fourth sentence unexpectedly writes a data to this storage area! This is a serious mistake. So when using pointers, programmers must be very clear about where my pointers are pointing. When accessing an array with a pointer, be careful not to go beyond the low-end and high-end boundaries of the array, otherwise a similar error will occur.

In the forced type conversion of the pointer: 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 storage pointed to by ptr2. If sizeof (the type of ptr2) is less than sizeof (the type of ptr1), it is not safe to use the pointer ptr1 to access the storage that ptr2 points to. As for why, readers should understand if they think about it in the light of example 18.

The content of "detailed explanation of C pointer related knowledge points" is introduced here. Thank you for your reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report