In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-22 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article mainly introduces "summarizing C language pointers from underlying principles to fancy skills". In daily operation, I believe many people have doubts in summarizing C language pointers from underlying principles to fancy skills. The editor consulted all kinds of materials and sorted out simple and easy-to-use operation methods. I hope it will be helpful to answer the doubts of "summarizing C language pointers from underlying principles to fancy skills". Next, please follow the editor to study!
I. Preface
If you ask what is the most important and powerful concept in C language, the answer must be pointer! Powerful, it means easy to use, efficient, but also means that the grammar is complex and error-prone. If the pointer is used well, it can greatly improve the efficiency of code execution and save system resources; if not, the program will be full of traps and loopholes.
In this article, let's talk about pointers. Start from the lowest level of memory storage space, all the way to the application layer of a variety of pointer skills, step by step, peeling cocoons, explain in the most straightforward language, let you have fun at once.
Note: in order to facilitate explanation and understanding, the address of the memory space in the paper is written casually, and the address alignment should be followed in the actual computer.
Second, the essence of variables and pointers
1. Memory address
After we write a program source file, the compiled binary executable file is stored on the computer's hard disk. At this time, it is a static file, commonly called a program.
When this program is started, the operating system will do the following things:
Copy the contents of the program (code snippet, data segment) from the hard disk to memory
Create a data structure PCB (process control block) to describe various information about the program (e.g. resources used, open file descriptors.)
Locate the address of the entry function in the code snippet and let CPU execute from that address.
When a program begins to be executed, it becomes a dynamic state, commonly referred to as a process.
Memory is divided into physical memory and virtual memory. The operating system manages and packages the physical memory, and we developers are faced with the virtual memory provided by the operating system.
These two concepts do not hinder the understanding of the article, so they are called memory.
In our program, variables are defined and used by a variable name. The variable itself is a real thing, and the variable name is an abstract concept used to represent the variable. For example, I am a real person, and I objectively exist on this earth. Brother Dao is a name I gave myself. This name is taken at will, as long as I feel good to it. If I want to, I can also call it Brother Bird, Brother long and so on.
So, after we define a variable, where do we put it? That is the data area of memory. Memory is a large storage area, which is divided into a small space by the operating system, and the operating system manages the memory by address.
The minimum storage unit in memory is bytes (8 bit), and the complete space of a memory is made up of consecutive bytes. In the image above, each small grid represents a byte, but it seems that people do not draw memory models in this way in books, and it is more common to draw them like this:
That is to draw 4 consecutive bytes of space together, so that it is easy to express and understand, especially when it comes to the relevant knowledge of code alignment. (I think the root cause should be: everyone draws like this, and it is pleasing to the eye.)
2. 32 bit and 64 bit system
The computer we usually talk about is 32-bit and 64-bit, which refers to the maximum storage length of the register in the computer's CPU. If the maximum storage of 32bit data in the register, it is called a 32-bit system.
In a computer, data is generally accessed back and forth between hard drives, memory and registers. CPU connects the components through three kinds of buses: address bus, data bus and control bus. The width of the address bus determines the addressing ability of the CPU, that is, the maximum address range that the CPU can reach.
As I just said, memory is managed by address, so CPU wants to access a data from some address space in memory, so CPU needs to output the address of this storage unit on the address bus. If the width of the address bus is 8 bits, the maximum address space that can be represented is 256 bytes, and the largest storage cell that can be found in memory is 255 (starting with 0). Even if the actual space of the memory stick is 2 gigabytes, CPU cannot use the following memory address space. If the width of the address bus is 32 bits, then the maximum address that can be represented is 2 to the 32, that is, 4G bytes of space.
[note]: here only describes the concept of address bus, the actual computer address calculation is much more complex, such as: virtual memory using segmentation, paging, offset to locate the actual physical memory, there are large pages and small pages in the paging, interested students can check the relevant information.
3. Variable
We use variables in C programs to "represent" a data and a function name to "represent" a function. Variable names and function names are mnemonic characters used by programmers. Variables and functions eventually have to be put in memory before they can be used by CPU, and all the information in memory (code and data) is stored in binary form, so the computer will not distinguish between code and data according to the format. CPU needs an address when accessing memory, not a variable name or a function name.
The question arises: how do you map (associate) the two when you use variable names to refer to variables in program code, and variables are stored in memory according to their addresses?
The answer is: compiler! When compiling a C program file in text format, where does the compiler run according to the target platform (that is, the compiled binary program)? Is it a computer on x86 platform? Or the development board of the ARM platform?) To arrange various addresses in the program, such as the address loaded into memory, the entry address of the code snippet, and so on, and the compiler will convert all the variable names in the program to the storage address of the variable in memory.
Variables have two important attributes: the type of variable and the value of the variable.
Example: a variable is defined in the code
Int a = 20
The type is int and the value is 20. The storage model of this variable in memory is:
We use the variable name an in the code, which means that the data in the storage unit corresponding to the 0x11223344 address is used when the program is executed. Therefore, it can be understood that the variable name an is equivalent to this address 0x11223344. In other words, if we can know in advance that the compiler arranges the variable an in the address 0x11223344 cell, we can manipulate the variable directly with this address value in the program.
In the figure above, the value of the variable an is 20, which occupies four squares of space in memory, that is, four bytes. Why 4 bytes? The C standard does not stipulate that variables of each data type must occupy several bytes, which is related to the specific machine and compiler.
For example, in a 32-bit compiler:
Char: 1 byte; short int: 2 bytes; int: 4 bytes; long: 4 bytes.
For example, in a 64-bit compiler:
Char: 1 byte; short int: 2 bytes; int: 4 bytes; long: 8 bytes.
For ease of description, the following examples are 32 bits, that is, int variables occupy 4 bytes in memory.
In addition, 0x11223345, 0x11223345, 0x11223346, 0x11223347, the consecutive four bytes from the low address to the high address are used to store the value 20 of the variable a. In the diagram, hexadecimal is used to show that the decimal value 20 is converted to hexadecimal: 0x00000014, so the four bytes 0x00, 0x00, 0x00, and 0x14 are stored in turn from the starting address (the storage order involves the size of the end, and does not affect the understanding of the text).
According to this illustration, if you want to know where the variable an is stored in memory in the program, you can use the address operator &, as follows:
Printf ("& a = 0x%x\ n", & a)
This sentence will be printed: & a = 0x11223344.
Consider that in a 32-bit system: how many bytes does a pointer variable take?
4. Pointer variable
Pointer variables can be understood at two levels:
A pointer variable is first and foremost a variable, so it has all the properties of the variable: type and value. Its type is a pointer, and its value is the address of other variables. Since it is a variable, you need to allocate a storage space for the variable in memory. In this storage space, the addresses of other variables are stored.
The data type that the pointer variable points to, which is determined when the pointer variable is defined. For example: int * p; means that the pointer points to an int type of data.
First of all, to answer the question, in a 32-bit system, a pointer variable occupies 4 bytes of space in memory. Because when CPU addresses the memory space, it uses 32-bit address space (4 bytes), that is, it can store the address of a memory unit with 4 bytes. The value in the pointer variable stores the address, so 4 bytes of space is needed to store the value of a pointer variable.
Example:
Int a = 20; int * pa; pa = & a; printf ("value =% d\ n", * pa)
The storage model in memory is as follows:
For the pointer variable pa, first of all, it is a variable, so there needs to be a space in memory to store the variable, and the address of this space is 0x11223348
Second, what is stored in this memory space is the address of the variable a, and the address of an is 0x11223344, so the value 0x11223344 is stored in the address space of the pointer variable pa.
Here are two operators & and *:
&: take the address operator to get the address of a variable. The & an in the above code is used to get the memory address of the variable an in memory, that is, 0x11223344.
*: this operator is used in two scenarios: when defining a pointer and getting the value of a variable pointed to by a pointer.
The variable pa that is defined in the int pa; statement is a pointer, and the previous int indicates that the pointer pa points to a variable of type int. However, at this time, we did not assign a value to pa, that is to say, the value in the 4 bytes in the corresponding memory cell of pa is not initialized. It may be 0x00000000 or any other number. It is uncertain.
The * in the printf statement means to get the value of the int type variable that pa points to. The scientific name is dereference. We just need to remember that we are getting the value of the variable pointed to.
5. Operation pointer variable
Operations on pointer variables include three aspects:
Hongmeng official Strategic Cooperation to build HarmonyOS Technology Community
Manipulate the value of the pointer variable itself
Gets the data pointed to by the pointer variable
What data type to use / interpret what the pointer variable points to.
5.1 value of the pointer variable itself
Int a = 20; this statement defines the variable a, and in the subsequent code, simply writing down an indicates that you want to manipulate the value stored in the variable a. There are two operations: read and write.
Printf ("a =% d\ n", a); this statement is to read the value in variable a, which is, of course, 20
A = 100; this statement is to write a value of 100 to the variable a.
By the same token, the int * pa; statement is used to define the pointer variable pa. In the subsequent code, simply writing pa indicates that you want to manipulate the value in the variable pa:
Printf ("pa =% d\ n", pa); this statement reads the value in the pointer variable pa, which is, of course, 0x11223344
Pa = & a; this statement is to write the new value to the pointer variable pa. Again, the address is stored in the pointer variable, and if we can know in advance that the address of the variable an is 0x11223344, then we can also assign it like this: pa = 0x11223344
Think about what the print result would be if you executed the statement printf ("& pa = 0x%x\ n", & pa);.
As mentioned above, the operator & is used to get the address, then & pa means to get the address of the pointer variable pa. The above memory model shows that the pointer variable pa is stored in the address 0x11223348, so the printed result is: & pa = 0x11223348.
5.2 get the data pointed to by the pointer variable
The data type that the pointer variable points to is clear when it is defined, that is, the data type pointed to by the pointer pa is int, so when executing the printf ("value =% d\ n", * pa); when you execute the statement, you first know that pa is a pointer in which an address (0x11223344) is stored, and then use the operator * to get the value in the storage space corresponding to this address (0x11223344). And because when defining pa, we have specified that the value it points to is of type int, so we know that the address 0x11223344 stores data of type int.
5.3 what data types are used to use / interpret what pointer variables point to
The code is as follows:
Int a = 30000; int * pa = & a; printf ("value =% d\ n", * pa)
From the above description, we know that the print result of printf will be value = 30000, and the decimal 30000 converted to hexadecimal is 0x00007530. The memory model is as follows:
Now let's do this test:
Char * pc = 0x11223344; printf ("value =% d\ n", * pc)
When the pointer variable pc is defined, it indicates that the data type it points to is char, and the address stored in the pc variable is 0x11223344. When you use * pc to get the data pointed to, the data at the 0x11223344 address will be read in char format, so value = 0 will be printed (in the computer, ASCII codes are stored with equivalent numbers).
This example illustrates an important concept: everything is a number in memory, and it is entirely up to our code to tell the compiler how to manipulate (interpret) the data in a memory address. In this example, although the value of the integer variable an is stored in the first four bytes of the 0x11223344 address, it is perfectly legal to have the pc pointer use / interpret the contents of this address in terms of char data.
The above is the most fundamental mental method of the pointer. If you understand this method of mind, all that is left is a question of more knowledge and practice.
Third, several related concepts of pointer
1. Const attribute
The const identifier is used to represent the immutable properties of an object, such as a definition:
Const int b = 20
The value of the variable b cannot be changed later in the code, and the value in b is always 20. Similarly, if you modify a pointer variable with const:
Int a = 20; int b = 20; int * const p = & a
The memory model is as follows:
The const here is used to modify the pointer variable p. According to the nature of const, it can be concluded that after p is defined as the address of the variable a, it is fixed and cannot be changed, that is to say, the pointer variable pa can only store the address 0x11223344 of the variable a. If p = & b is written later in the code, an error will be reported at compile time, because p is immutable and can no longer be set to the address of the variable b.
However, the value of the variable a pointed to by the pointer variable p can be changed, that is, * p = 21; this statement is legal because the value of the pointer p does not change (it is still the address of the variable c 0x11223344), but the value stored in the variable c is changed.
Distinguish it from the following code:
Int a = 20; int b = 20; const int * p = & a; p = & b
The const here is not placed next to p, but next to the type int, which means that the const symbol is not used to modify p, but to modify the variable that p points to. So, if we write p = & b; assign the address of the variable b to the pointer p, it's legal because the value of p can be changed.
But this statement * p = 21 is illegal because the const in the definition statement limits the data obtained through the pointer p, which cannot be changed and can only be used to read. This property is often used on function parameters, such as the following code, which calculates the CRC check of a piece of data. This function only needs to read the original data and does not need (and cannot) change the original data, so you need to use the const modifier on the formal parameter pointer:
Short int getDataCRC (const char * pData, int len) {short int crc = 0x0000; / / calculate CRC return crc;}
2. Void pointer
The keyword void is not a real data type, it reflects an abstraction, indicating that it is not of any type, and there are generally two usage scenarios:
Hongmeng official Strategic Cooperation to build HarmonyOS Technology Community
The return value and formal parameters of the function
Pointers are defined without explicitly specifying the type of data they refer to, which means that they can point to any type.
Pointer variables are also a kind of variables. Variables can be assigned to each other, so pointer variables can also be assigned to each other, for example:
Int a = 20; int b = a; int * p1 = & a; int * p2 = p1
The variable an is assigned to the variable b, and the pointer p1 is assigned to the pointer p2. Note that they must be of the same type: both an and b are int, and p1 and p2 point to int, so they can be assigned to each other. What if the data types are different? A cast must be performed. For example:
Int a = 20; int * p1 = & a; char * p2 = (char *) p1
The memory model is as follows:
The p1 pointer points to int data, and now you want to assign its 0x11223344 to p2, but because the data type it points to when defining the p2 pointer is char, it is necessary to cast the pointer p1, that is, to treat the data at the address 0x11223344 as char data before assigning a value to the p2 pointer.
If we use void * p2 to define p2 pointers, then there is no need to cast when assigning values, for example:
Int a = 20; int * p1 = & a; void * p2 = p1
Pointer p2 is of void* type, which means that any type of pointer can be assigned to p2, but not vice versa, that is, void* pointers cannot be assigned directly to pointers of other definite types, but must be forcibly converted to the data type pointed to by the assigned pointers. The following code shows that p2 pointers must be forcibly converted to int*, and then assigned to p3 pointers:
Int a = 20; int * p1 = & a; void * p2 = p1; int * p3 = (int *) p2
Let's look at a system function:
Void* memcpy (void* dest, const void* src, size_t len)
The first parameter type is void*, which reflects the true meaning of the system to memory operations: it doesn't care what data type the pointer sent by the user points to, but stores the data one by one in the space corresponding to this address.
The same is true for the second argument, along with the addition of the const modifier, which means that the memcpy function only reads data from the src pointer and does not modify it.
3. Null pointer and wild pointer
A pointer must point to a meaningful address before it can be manipulated. If the address value stored in the pointer is a random value, or a value that has been invalidated, the operation pointer is very dangerous. Such pointers are generally called wild pointers, which is the source of many pointer-related bug in C code.
3.1 Null pointer: a pointer that points to nothing
After defining a pointer variable, if there is no assignment, then what is stored in the pointer variable is a random value, which may point to any address space in memory. This pointer must not be written at this time. Because it may point to the code snippet area in memory, or it may point to the area where the operating system is located in memory.
Generally, a pointer variable is assigned to NULL to represent a null pointer. In C language, NULL is essentially ((void*) 0), and in C++, NULL is essentially 0. In the standard library header file stdlib.h, there are the following definitions:
# ifdef _ cplusplus # define NULL 0 # else # define NULL ((void *) 0) # endif
3.2 Wild pointer: pointer whose address has expired
As we all know, the local variables in the function are stored in the stack area, and the memory space requested through malloc is located in the heap area, as shown in the following code:
Int * p = (int *) malloc (4); * p = 20
The memory model is:
After requesting 4 bytes of space in the heap area and then forcing the conversion to int*, assign a value to the pointer variable p, and then set the value in this address to 14 through * p, which is legal. If you use * p to manipulate this address after releasing the space pointed to by the p pointer, it is very dangerous, because this address space may have been allocated by the operating system to other code. If you force the data in this address and the program crashes immediately, it will be our greatest luck!
Int * p = (int *) malloc (4); * p = 20; free (p); / / you can no longer manipulate the data in the p pointer after free. P = NULL; / / it's best to add this sentence.
Pointers to different data types
1. Numerical pointer
From the above introduction, the pointer to a numeric variable is clear, and what you need to pay attention to is the type of data the pointer points to.
two。 String pointer
There are two representations of strings in memory:
Represented by an array, for example: char name1 [8] = "zhangsan"
Represented by a char * pointer, for example: char * name2 = "zhangsan"
Name1 occupies 8 bytes in memory, in which 8-character ASCII code values are stored; name2 occupies 9 bytes in memory, because in addition to storing 8-character ASCII code values, there is an additional'\ 0 'after the last character' n'to identify the end of the string.
For strings, it is very convenient to use pointers, such as the variable string name2:
Char * name2 = "zhangsan"; char * p = name2; while (* p! ='\ 0') {printf ("% c", * p); p = p + 1;}
In the while judgment condition, check whether the character pointed to by the p pointer is the Terminator'\ 0'. After cycling the weight and printing out the characters currently pointed to, the pointer is incremented there, because the data type pointed to by the pointer p is char, and each char occupies a byte in memory, so the pointer p points to the next storage space after increasing by 1.
You can also write two statements in the body of the loop into one statement:
Printf ("% c", * paired +)
If a pointer points to an int data type, execute p = p + 1; after that, the address value stored in the pointer p will increase by 4, because an int data occupies 4 bytes of space in memory, as shown below:
Consider a question: can void* pointers be incremented? Test the code as follows:
Int a [3] = {1,2,3}; void * p = a; printf ("1: P = 0x%x\ n", p); p = p + 1; printf ("2: P = 0x%x\ n", p)
The print result is as follows:
1: P = 0x733748c0 2: P = 0x733748c1
It shows that when the void* pointer is incremented, it is calculated according to the span of one byte.
3. Pointer array and array pointer
These two statements are often confused, at least I am. Let's take a look at these two sentences:
Int * p1 [3]; / / pointer array int (* p2) [3]; / / array pointer
3.1 pointer array
In the first statement: brackets [] have high priority, so they are combined with p1 to represent an array of three elements, all of which are pointers, pointing to int data. It can be understood this way: if you have this definition char p [3], it is easy to understand that this is an array with three char elements, then replacing char with int*, means that the element type in the array is of type int* (a pointer to int data). The memory model is as follows (note: the addresses pointed to by the three pointers are not necessarily contiguous):
If you assign values to elements in a pointer array, you need to assign the address of the variable to the pointer element one by one:
Int a = 1, b = 2, c = 3; char * p1 [3]; p1 [0] = & a; p1 [1] = & b; p1 [2] = & c
3.2 Array pointer
In the second statement: parentheses combine p2 with *, indicating that p2 is a pointer to an array of three elements, each of which is of type int. It can be understood this way: if you have this definition int p [3], it is easy to understand that this is an array with three char elements, then change the array name p to * p2, that is, p2 is a pointer to the array. The memory model is as follows (note: the address pointed to by the pointer is an array in which three elements are placed successively in memory):
Earlier we talked about the address operator & which is used to get the address of a variable. There are special circumstances in everything, and the following situations do not require the use of the & operator to obtain an address:
When the literal amount of a string is used as the right value, it represents the first address of the string in memory.
The array name represents the address of the array, which is also equal to the address of the first element of the array
The function name represents the address of the function.
So, for the following code, the print result of the three printf statements is the same:
Int a [3] = {1,2,3}; int (* p2) [3] = a; printf ("0x%x\ n", a); printf ("0x%x\ n", & a); printf ("0x%x\ n", p2)
Think about it, if you perform p2 = p2 + 1 on the p2 pointer here, how much will the value in p2 increase?
The answer is 12 bytes. Because p2 points to an array that contains three elements, each occupying 4 bytes, the array occupies a total of 12 bytes in memory, so p2 skips 12 bytes after adding 1.
4. Two-dimensional array and pointer
One-dimensional array is composed of continuously distributed memory units in memory, while two-dimensional array is also composed of continuously distributed memory units in memory. From the memory point of view, there is no essential difference between one-dimensional array and two-dimensional array.
Similar to an one-dimensional array, the array name of a two-dimensional array represents the first address of the first element in the first-dimensional array of a two-dimensional array, which is illustrated by code:
Int a [3] [3] = {{1p0) [3] [3] = {{1p2] [3], {7p8}}; / / two-dimensional array int (* p0) [3] = NULL; / / p0 is a pointer to an array int (* p1) [3] = NULL; / / p1 is a pointer to an array int (* p2) [3] = NULL; / / p2 is a pointer to an array p0 = a [0] P1 = a [1]; p2 = a [2]; printf ("0:% d% d% d\ n", * (* p0 + 0), * (* p0 + 1), * (* p0 + 1), * (* p0 + 2); printf ("1:% d% d\ n", * (* p1 + 0), * (* p1 + 1), * (* p1 + 2)) Printf ("2:% d% d% d\ n", * (* p2 + 0), * (* p2 + 1), * (* p2 + 2))
The print result is:
0: 1 2 3 1: 4 5 6 2: 7 8 9
Let's analyze the first printf statement: P0 is a pointer to an array containing three elements, each of which occupies four bytes in memory. Now we want to get the data in this array, if we add 1 directly to p0, then p0 will span 12 bytes (equal to the value in p1), so we need to use the dereferencing operator *. Change p0 to an int pointer, and then add 1 to get the int data in the array.
5. Structure pointer
The basic data types in C language are predefined, the structure is user-defined, and analogy can be made in the use of pointers. The only difference is that in the structure pointer, you need to use the-> arrow operator to get the member variables in the structure, for example:
Typedef struct {int age; char name [8];} Student; Student s; s.age = 20; strcpy (s.name, "lisi"); Student * p = & s; printf ("age =% d, name =% s\ n", p-> age, p-> name)
It doesn't seem to have any technical content. What if it's a structural array? For example:
Student s [3]; Student * p = & s; printf ("sizeof Student =% d\ n", sizeof (Student)); printf ("1: 0x%x, 0x%x\ n", s, p); printf ("2: 0x%x\ n", p)
The print result is:
Size of Student = 121: 0x4c02ac00, 0x4c02ac00 2: 0x4c02ac0c
After performing the pause + operation, the space p needs to cross is the size of a structure variable in memory (12 bytes), so at this point p points to the first address of the second element in the array, and the memory model is as follows:
6. Function pointer
After each function is compiled, it becomes a collection of multiple instructions, and after the program is loaded into memory, the instruction set is placed in the code area. We use the function name in the program to represent the starting address of the instruction set.
A function pointer is still essentially a pointer, except that the pointer variable stores the address of a function. What is the most important feature of a function? Can be called! Therefore, when a function pointer is defined and a function address is assigned to the pointer, the function can be called through the function pointer.
The example code is as follows:
Int add (int XJI int y) {return x int y;} int main () {int a = 1, b = 2; int (* p) (int, int); p = add; printf ("% d +% d =% d\ n", a, b, p (a, b));}
As mentioned earlier, the name of the function represents the address of the function, so the function name add represents the address of the addition function in memory. Int (* p) (int, int); this statement is used to define a function pointer that points to a function that must meet the following two points (scientific name: function signature):
Hongmeng official Strategic Cooperation to build HarmonyOS Technology Community
There are 2 int parameters
There is an int return value.
The add function in the code meets this requirement, so you can assign add to the function pointer p, which points to the address where the function is stored in memory, and then you can call the function with the function pointer p.
In the sample code, the function pointer p is defined directly, so if you want to define two function pointers, do you need to define it like this?
Int (* p) (int, int); int (* p2) (int, int)
The parameters here are relatively simple, if the function is very complex, isn't this definition annoying to death? You can use the typedef keyword to define a function pointer type:
Typedef int (* pFunc) (int, int)
Then it is much more convenient to pFunc p1, p2; in this way to define multiple function pointers. Note: only functions with the same signature as the function pointer type can be assigned to p1 and p2, that is, the number and type of parameters should be the same, and the return value should be the same.
Note: here are a few small details:
It is also possible to use p = & a; when assigning function pointers.
It is also possible to use (* p) (a, b); when calling with a function pointer.
There is no special principle to explain here, in the end, it is the compiler that helps us deal with the details here, just remember it directly.
After the function pointer is understood, it is combined with an array: an array of function pointers. The sample code is as follows:
Int add (int a, int b) {return a + b;} int sub (int a, int b) {return a-b;} int mul (int a, int b) {return a * b;} int divide (int a, int b) {return a / b;} int main () {int a = 4, b = 2; int (* p [4]) (int, int); p [0] = add; p [1] = sub P [2] = mul; p [3] = divide; printf ("% d +% d =% d\ n", a, b, p [0] (a, b)); printf ("% d -% d =% d\ n", a, b, p [1] (a, b)); printf ("% d *% d =% d\ n", a, b, p [2] (a, b) Printf ("% d /% d =% d\ n", a, b, p [3] (a, b));}
This sentence is not easy to understand: int (* p [4]) (int, int); first analyze the middle part, identifier p is combined with brackets [] (high priority), so p is an array with four elements in the array; then the rest represents a function pointer, which means that the element type in the array is the function pointer, that is, the address of other functions, and the memory model is as follows:
If it's still hard to understand, go back to the essential concept of a pointer: a pointer is an address! It doesn't matter what is stored in this address, what matters is that you tell the computer what it is. If you tell it that the content stored in this address is a function, then the computer will call the function. So how do you tell the computer that when defining pointer variables, that's all!
At this point, the study of "summing up C language pointers from underlying principles to fancy skills" is over. I hope to be able to solve your doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!
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.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.