0 foreword
Pointers are the most important and most difficult part of C language to understand. They are everywhere in our daily work. Some people say that if you learn Pointers, you can only learn half of C language. Why is pointer hard. Because combining a pointer with an array involves an array pointer with a pointer array. The combination of a pointer and a structure involves a structure pointer. Combining a pointer with a character involves a character pointer. Combining a pointer with const involves constant Pointers and pointer constants. The combination of Pointers and functions involves function Pointers and pointer functions, as well as callback functions. Pointers and pointer combinations involve two-dimensional Pointers. The author has been troubled by these problems for a long time. So I found many blogs on the Internet to answer my doubts. In this article, I try to present the above knowledge points in the form of examples. I believe that by reading this article, you will have a deeper understanding of Pointers. The examples in this article are all from the Internet.
1 Definition of a pointer
We know that ordinary variables store a value. A pointer variable, on the other hand, also stores a value, only this is a special value: its value is the address of another variable.
A pointer is defined as follows:
datatype *name; Datatype *name = value;Copy the code
Name is a pointer to an address of type dataype. A pointer stores an address. If you want to get the contents of this address, you can get it by dereferencing it with * :
int a = 12; int *pa = &a; printf("*pa:%u.", *pa); // Output is 12; *pa = 14; // The value of a is 14Copy the code
One thing to note here, and one that I’ve always been confused about before: when a pointer is defined, the compiler does not allocate space for the object to which the pointer points; it just allocates space for the pointer itself, unless it is also initialized by assigning a string constant. Such as:
int *a; . *a = 12;Copy the code
The above code snippet illustrates a very common error: we declare the variable but never initialize it, so there is no way to predict where the value 12 will be stored. If the variable is static, it will be initialized to 0; If the variable is automatic, it will not be initialized at all. In either case, declaring a pointer to an integer does not “create” the memory space used to store integer values. However, the following definition creates a string constant (for which memory is allocated) :
char *p = "breadfruit";
Copy the code
String constants created when the pointer is initialized are defined as read-only. If you try to change the value of the string through a pointer, the program will have undefined behavior.
Except that the above definitions are correct, all other definitions are wrong:
Float * PIP = 3.14; / / error! Failed to compileCopy the code
2 pointer operation
- Pointer +(-) integer
A pointer stores an address, which is essentially an integer, so you can add or subtract an integer. But instead of ordinary addition or subtraction, a pointer plus or minus an integer results in another pointer. But where does that pointer point to? When an arithmetic operation is performed on a pointer and an integer, the integer is adjusted to the appropriate size before the addition (subtraction) operation is performed. The “fit size” is the size of the type to which the pointer points, and the “adjust” is multiplying the integer value by the “fit size.”
#include <stdio.h> int main() { int a = 10; int *pa = &a; Double b = 99.9; double *pb = &b; char c = '@'; char *pc = &c; printf("sizeof(int)= %u, sizeof(double)=%u, sizeof(char)=%u\n", sizeof(int), sizeof(double), sizeof(char)); / / the initial value of printf (" & a = % p & p, b = % p & c = % \ n ", & a, & b, & c); printf("pa=%p, pb=%p, pc=%p\n", pa, pb, pc); // add operation pa++; pb++; pc++; printf("pa=%p, pb=%p, pc=%p\n", pa, pb, pc); // Subtraction operation pa -= 2; pb -= 2; pc -= 2; printf("pa=%p, pb=%p, pc=%p\n", pa, pb, pc); return 0; }Copy the code
Calculation result:
sizeof(int)= 4, sizeof(double)=8, sizeof(char)=1
&a=000000000061FE04, &b=000000000061FDF8, &c=000000000061FDF7
pa=000000000061FE04, pb=000000000061FDF8, pc=000000000061FDF7
pa=000000000061FE08, pb=000000000061FE00, pc=000000000061FDF8
pa=000000000061FE00, pb=000000000061FDF0, pc=000000000061FDF6
Copy the code
As can be seen from the above results, when the pointer pa, PB and PC are added by 1, the actual address is increased by the size of the corresponding type. Same thing with subtraction.
- Pointer – pointer
Subtracting from one pointer is only allowed if both Pointers point to elements in the same array. The result of subtracting two Pointers is the number of elements between them. For example, if p1 refers to array[I] and p2 refers to array[j], then the value p2-p1 is the value of j-i. If two Pointers do not point to elements in the same array, the result of subtraction between them is undefined and meaningless.
Pointer and array
3.1 Array Pointer (Pointer to an array)
Array pointer, it’s a pointer to an array. That is, it stores the address of an array variable. So every step that this pointer takes is the size of the array. Since it is the entire array at each step, it is also called an array of rows.
# include < stdio, h > int main () {int a [3] [4] = {{1, 2, 3, 4}, {5,6,7,8}, {9,10,11,12}}; int (*pa)[4]; pa = a; printf("a:%p, &a:%p, &a[0][0]:%p\n", a, &a, &a[0][0]); printf("pa:%p, (*pa)[0]:%u\n", pa, (*pa)[0]); pa++; printf("&a[1]:%p, &a[1][0]:%p\n", &a[1], &a[1][0]); printf("pa:%p, (*pa)[0]:%u\n", pa, (*pa)[0]); return 0; }Copy the code
Running result:
a:000000000061FDE0, &a:000000000061FDE0, &a[0][0]:000000000061FDE0
pa:000000000061FDE0, (*pa)[0]:1
&a[1]:000000000061FDF0, &a[1][0]:000000000061FDF0
pa:000000000061FDF0, (*pa)[0]:5
Copy the code
First, pa is an array pointer. It first stores the address of the first element of array A. Since the array name is also the first address of array, the addresses of a, &a, &a[0][0] are the same. That’s the same address that’s stored in PA. I’m going to dereferencing pa, *pa to get this array, and then (*pa)[I] is going to get the elements of this array with index I.
3.2 Pointer Arrays
Pointer array, it’s essentially an array, except the entire array is of a pointer type.
#include<stdio.h>
int main(void)
{
char *p1 = "Himanshu";
char *p2 = "Arora";
char *p3 = "India";
char *arr[3];
arr[0] = p1;
arr[1] = p2;
arr[2] = p3;
printf("\n p1 = [%s] \n",p1);
printf("\n p2 = [%s] \n",p2);
printf("\n p3 = [%s] \n",p3);
printf("\n arr[0] = [%s] \n",arr[0]);
printf("\n arr[1] = [%s] \n",arr[1]);
printf("\n arr[2] = [%s] \n",arr[2]);
return 0;
}
Copy the code
Running result:
p1 = [Himanshu]
p2 = [Arora]
p3 = [India]
arr[0] = [Himanshu]
arr[1] = [Arora]
arr[2] = [India]
Copy the code
References: www.thegeekstuff.com/2012/01/adv…
4 Pointer and character
In C language, there are usually two forms of representation string, one is an array form, and the other is a character pointer form. Array form:
char arr[] = "hello,world";
Copy the code
Character pointer form:
char *str = "hello,world";
Copy the code
Although both forms can represent strings, there are some differences:
- storage
A character array consists of several elements, each of which holds a character. A character pointer variable holds only the first address of the string, not the entire string.
- Storage location.
Array is a memory space to store strings, is the stack area. A character pointer, on the other hand, creates a space in the literal constant area to store the string, giving the first address of the string to a pointer variable, STR.
- Assignment mode.
For arrays, the following assignment is incorrect:
Char STR [10]. STR = "hello"; / / error!Copy the code
For character pointer variables, the following method can be used:
char *a;
a = "hello";
Copy the code
- Can be modified.
The contents of the string to which a pointer variable points cannot be modified, but the value of the pointer variable (i.e., the address or pointer) can be modified.
5 Pointers and structures
A pointer that points to a struct type is called a struct pointer. A structure can also have pointer members among its members.
struct{ char *name; Int num; // Student id int age; // Age char group; // Group float score; } / / performance stu1 = {" Tom ", 12, 18, 'A', 136.5}, * pstu = & stu1;Copy the code
In the above code, a struct variable stu1 is defined. This variable has a pointer variable name in it. A struct pointer PSTU is also defined. There are usually two ways to access a struct member through a struct pointer:
(*pstu).name;
pstu->name;
Copy the code
6 Pointer and const: constant Pointers and pointer constants
References: www.thegeekstuff.com/2012/06/c-c… Eli.thegreenplace.net/2003/07/23/…
Beginners often get these two concepts wrong. First of all, I think we need to understand what we mean by constant here. Constants are only readable and cannot be modified. Which one is only readable but not modifiable, a pointer or a pointer constant? Is it the pointer or what the pointer points to? Here’s a way to quickly figure out which ones are unmodifiable. The declaration is bounded by an asterisk (*) and divided into two parts, the one to the left and the one to the right of the asterisk. Const is only readable and cannot be modified. Consider the following code: bounded by an asterisk (*), char to the left of the asterisk, and no const keyword, so it points to something other than a constant. Then, to the right of the asterisk is const PTR, so we can say that PTR is a constant. So, this line of code declares a pointer to a constant but points to something that is not a constant. So this is a pointer constant.
char* const ptr = "just a string";
Copy the code
Similarly, we can analyze the following code:
// Neither the data nor the pointer are const
//
char* ptr = "just a string";
// Constant data, non-constant pointer
//
const char* ptr = "just a string";
// Constant pointer, non-constant data
//
char* const ptr = "just a string";
// Constant pointer, constant data
//
const char* const ptr = "just a string";
Copy the code
6.1 Constant Pointers
Constant Pointers: This is essentially a Constant, except that it’s a pointer. Since Pointers are only readable and cannot be modified, this pointer cannot point to another address, but the contents of that address can be changed. A pointer constant is declared in the following format:
<type of pointer> * const <name of pointer>Copy the code
Let’s look at the following program:
#include<stdio.h>
int main(void)
{
int var1 = 0, var2 = 0;
int *const ptr = &var1;
ptr = &var2;
printf("%d\n", *ptr);
return 0;
}
Copy the code
In the program above:
- We first defined two variables var1,var2;
- Then, we define a pointer constant, PTR, and point to VAR1
- Next, try to have the PTR point to VAR2
- Finally, print out the contents of the address to which the pointer PTR points
Let’s run the program:
main.c: In function 'main':
main.c:6:9: error: assignment of read-only variable 'ptr'
ptr = &var2;
^
Copy the code
We see that the program compiled incorrectly: it attempted to assign a value to the read-only variable PTR. So, once we define a pointer constant, that pointer cannot point to any other variable. However, we can still change the contents of the directed address:
#include<stdio.h>
int main(void)
{
int var1 = 0;
int *const ptr = &var1;
*ptr = 10; // OK
printf("%d\n", *ptr); // 10
return 0;
}
Copy the code
6.2 Pointer to Constant
Pointer to constant: It is essentially a Pointer except that the value it points to is constant (readable only, not modifiable). Since it points to a value that can only be read and not modified, the pointer cannot indirectly change the value of the address it stores, but it can point to another variable.
The declaration format of a constant pointer is as follows:
Const int* PTR; / / Const <type of pointer>* <name of pointer>Copy the code
Again, there is a procedure:
#include<stdio.h>
int main(void)
{
int var1 = 0;
const int* ptr = &var1;
*ptr = 1;
printf("%d\n", *ptr);
return 0;
}
Copy the code
Let’s analyze the program:
- We define a variable var1 and initialize it to 0
- We then define a pointer constant, PTR, and point it to VAR1
- Next, an attempt is made to change the value of VAR1 through the pointer PTR
- Finally, the contents of the address to which the PTR points are printed.
Let’s compile:
main.c: In function 'main':
main.c:7:10: error: assignment of read-only location '*ptr'
*ptr = 1;
^
Copy the code
* PTR is read-only. Therefore, the value of VAR1 cannot be changed by PTR. However, we can point PTR to another variable:
#include<stdio.h>
int main(void)
{
int var1 = 0;
const int* ptr = &var1;
printf("%d\n", *ptr); // 0
int var2 = 20;
ptr = &var2; // OK
printf("%d\n", *ptr); // 20
return 0;
}
Copy the code
6.3 Constant pointer to a constant
Once you understand the above two types, this is easy to understand. A constant pointer to a constant is a pointer that can neither point to another address nor modify the content through the address. Its declaration format is as follows:
Const const <type of pointer>* const <name of pointer>Copy the code
Similarly, in the next section of the program, I’m sure you know where the compilation error is.
#include<stdio.h>
int main(void)
{
int var1 = 0,var2 = 0;
const int* const ptr = &var1;
*ptr = 1;
ptr = &var2;
printf("%d\n", *ptr);
return 0;
}
Copy the code
Compile results:
main.c: In function 'main':
main.c:7:10: error: assignment of read-only location '*ptr'
*ptr = 1;
^
main.c:8:9: error: assignment of read-only variable 'ptr'
ptr = &var2;
^
Copy the code
7 Pointers and functions
7.1 Function Pointers
There are two ways to combine a pointer with a function: a pointer function and a function pointer. A pointer function is essentially a function whose return value is a pointer.
int * func(int x, int y);
Copy the code
Reference: blog.csdn.net/qq_33757398…
The function name itself is a pointer (address), which is the entry address of the function.
#include <stdio.h>
int sum(int a, int b)
{
return a + b;
}
int main()
{
printf("%p\n", sum);
return 0;
}
Copy the code
Output: 0000000000401550
A function pointer, in essence, is a pointer. It just happens to store the address of a function. Function pointer variables are defined in the following format:
Return value (* variable name)(argument list)Copy the code
Such as:
#include <stdio.h>
int sum(int a, int b)
{
return a + b;
}
int main()
{
printf("%p\n", sum);
int (*psum)(int, int); // 函数指针变量,参数名可以省略
psum = sum;
printf("%p\n", psum);
return 0;
}
Copy the code
Output:
0000000000401550, 0000000000401550,Copy the code
You can see that the two addresses are equal.
Function pointer type:
Typedef return value (* type name)(argument list);Copy the code
Such as:
typedef int(*PSUM)(int, int);
PSUM pSum2 = sum;
PSUM pSum3 = sum;
Copy the code
PSUM (* PSUM)(int, int); PSUM (* PSUM)(int, int); To define a function pointer variable.
#include <stdio.h>
int sum(int a, int b)
{
return a + b;
}
int func2(int a, int b)
{
return a - b;
}
typedef int (*PFUNC) (int, int);
int main()
{
int (*psum)(int, int);
psum = sum;
printf("psum(4, 5):%d\n", psum(4, 5));
PFUNC p2 = func2;
printf("p2(5, 2):%d\n", p2(5, 2));
p2 = sum;
printf("p2(5, 2):%d\n", p2(5, 2));
return 0;
}
Copy the code
Output:
psum(4, 5):9
p2(5, 2):3
p2(5, 2):7
Copy the code
7.2 Callback functions
Reference: zhuanlan.zhihu.com/p/214157226
Speaking of function Pointers, there is one more concept to mention — callback functions. Because it’s all too common in actual project code.
A callback function is a function called through a function pointer. If you pass a pointer to a function (address) as an argument to another function, we say it is a callback function when that pointer is used to call the function to which it points.
So why use callbacks? Or what are the benefits of using callbacks? Callbacks allow the user to pass a pointer to the method that needs to be called as an argument to a function, so that the function has the flexibility to use different methods when doing similar things.
How to use a callback function:
#include <stdio.h> int Callback_1(int a) ///< callback 1 {printf("Hello, this is Callback_1: a = %d \n", a); return 0; {printf("Hello, this is Callback_2: b = %d \n", b); return 0; {printf("Hello, this is Callback_3: c = %d \n", c); return 0; } int Handle(int x, int (*Callback)(int)); } int main() { Handle(4, Callback_1); Handle(5, Callback_2); Handle(6, Callback_3); return 0; }Copy the code
Like the code above: As you can see, the argument in Handle() is a pointer to the function Callback_1()/Callback_2()/Callback_3() that is passed to the Handle() function in main(). In other words, a callback function is simply a use of a function pointer.
8 Two-dimensional pointer
Two dimensional Pointers, or two level Pointers. It’s a pointer to a pointer. Such as:
#include<stdio.h>
int main()
{
int a = 10;
int *pa = &a;
int **ppa = &pa;
printf("%p, %p, %p, %p, %p", a, pa, *pa, ppa, *ppa);
return 0;
}
Copy the code
The output is as follows:
000000000000000A, 000000000061FE14, 000000000000000A, 000000000061FE08, 000000000061FE14
Copy the code
In the output, you can also see that *pa= 00000000000A, which is the same as the address of A. The content of PPA * PPA = 000000000061FE14 is also just equal to the address of PA. The memory relationship between them can be shown in the following figure:
Speaking of two-dimensional Pointers, we have to mention two-dimensional arrays. I’ve written about two-dimensional arrays and two-dimensional Pointers before, so you can check out this article.
8.1 Command Line Parameters
Handling command line arguments is one place where Pointers to Pointers come into play.
In general, the main function takes two parameters. The first, often called argc, represents the number of command-line arguments. The second, often called argv, refers to a set of parameter values. Since there is no inherent limit to the number of arguments, argv points to the first element of the set of argument values (essentially an array). Each of these elements is a pointer to a parameter text. If the program needs to access command-line arguments, the main function declares them.
int main(int argc, char **argv)
Copy the code
For example:
#include <stdio.h> int main(int argc, char *argv[]) { printf("argc: %d\n", argc); // Print the arguments until a NULL pointer is encountered. While (*++argv! = NULL) { printf("%s\n", *argv); } return 0; }Copy the code
On Windows: \test2.exe hello world
argc: 3
hello
world
Copy the code
Note that if you pass an argument on the command line that includes Spaces, you need to enclose the argument with “”, for example:.test2.exe “Hello word”.
argc: 2
hello word
Copy the code
9 the conclusion
That’s the end of this article on Pointers. I’m sure you know a lot more about Pointers. If you think this article is good, welcome to like, collection and reprint. If reproduced, please indicate the source.