1. What is the pointer
2. Pointer and pointer type
3. Field pointer
4. Pointer operation
5. Pointers and arrays
6. Secondary pointer
7. Pointer array
1, What is the pointer
What is the pointer? Two key points of pointer understanding:
1. Pointer is the number of the smallest unit in memory, that is, the address
2. The pointer in spoken English usually refers to the pointer variable, which is used to store the memory address
Conclusion: pointer is the address. In colloquial language, pointer usually refers to pointer variable.
Then we can understand it this way:
Memory
Memory | |
One byte | 0xFFFFFFFF |
One byte | 0xFFFFFFFE |
One byte | ... |
... | ... |
... | ... |
... | ... |
... | ... |
... | ... |
... | ... |
... | ... |
... | ... |
... | ... |
One byte | 0x00000002 |
One byte | 0x00000001 |
One byte | 0x00000000 |
Pointer variable
We can use & (address operator) to get the actual memory address of the variable, and store the address in a variable, which is a pointer variable
#include <stdio.h> int main() { int a = 10;//Open up a space in memory int *p = &a;//Here we take the address of variable a, and we can use the & operator. //The a variable occupies a space of 4 bytes. Here, the address of the first byte of the 4 bytes of a is stored in the p variable In, p Is a pointer variable. return 0; }
Summary:
Pointer variable, a variable used to store the address. (the values stored in the pointer are treated as addresses).
The problem here is:
- How big is a small unit? (1 byte)
- How to address?
After careful calculation and trade-off, we find that it is more appropriate to give a corresponding address to a byte.
For a 32-bit machine, if there are 32 address lines, it is assumed that the high level (high voltage) and low level (low voltage) generated by each address line during addressing are (1 or 0);
Then the address generated by the 32 address lines will be:
00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000001
...
11111111 11111111 11111111 11111111
There are 32 addresses to the power of 2. Each address identifies a byte, so we can address the idle 4G (2^32Byte == 2^32/1024KB == 2^32/1024/1024MB==2^32/1024/1024/1024GB == 4GB).
In the same way, the of 64 bit machines can be obtained
Here we understand:
- On a 32-bit machine, the address is 32 zeros or 1s to form a binary sequence, so the address must be stored in 4 bytes, so the size of a pointer variable should be 4 bytes.
- On a 64 bit machine, if there are 64 address lines, the size of a pointer variable is 8 bytes to store an address.
Summary:
- Pointers are used to store addresses, which uniquely identify an address space.
- The size of the pointer is 4 bytes on 32-bit platforms and 8 bytes on 64 bit platforms.
2, Pointer and pointer type
Here we are discussing the type of pointer
As we all know, variables have different types, integer, floating point, etc.
Does the pointer have a type?
To be exact: Yes.
When there is such a code:
int num = 10; p = #
To save & num (the address of Num) to p, we know that p is a pointer variable. What is its type?
We give the pointer variable the corresponding type.
char *pc = NULL; int *pi = NULL; short *ps = NULL; long *pl = NULL; float *pf = NULL; double *pd = NULL;
Here you can see that the pointer is defined as type +*
Actually:
A pointer of type char * is used to store the address of a variable of type char.
A pointer of type short * is used to store the address of a variable of type short.
Pointer of type int * is used to store the address of variable of type int.
What is the meaning of pointer type?
As follows:
one Pointer + - integer
#include <stdio.h> //Demonstration example int main() { int n = 10; char *pc = (char*)&n;//Cast to a pointer of type char * int *pi = &n; printf("%p\n", &n); printf("%p\n", pc);//Consistent with pi address printf("%p\n", pc+1);//+ 4 on pc address printf("%p\n", pi);//Consistent with pc address printf("%p\n", pi+1);//+ 1 at the address of pi return 0; }
Summary:
The type of pointer determines how far the pointer moves forward or backward.
2. Dereference of pointer
//Demonstration example #include <stdio.h> int main() { int n = 0x11223344; char *pc = (char *)&n; int *pi = &n; *pc = 0; //The number in the first byte becomes 0 and the others remain unchanged *pi = 0; //All the numbers in the four bytes become 0 return 0; }
Summary:
The type of pointer determines how much permission (several bytes can be operated) you have when dereferencing the pointer. For example, the dereference of char * pointer can only access one byte, while the dereference of int * pointer can access four bytes.
3, Field pointer
Concept: a wild pointer means that the position pointed to by the pointer is unknown (random, incorrect, and without explicit restrictions)
1. Cause of formation
(1) Pointer not initialized
#include <stdio.h> int main() { int *p;//The local variable pointer is uninitialized. It defaults to a random value and is not a wild pointer *p = 20; return 0; }
(2) Pointer out of bounds access
#include <stdio.h> int main() { int arr[10] = {0}; int *p = arr; int i = 0; for(i=0; i<=11; i++) { //When the range pointed to by the pointer exceeds the range of array arr, p is a wild pointer *(p++) = i; } return 0; }
(3) The space pointed to by the pointer is released
Here is the explanation when developing dynamic memory. You can give a simple prompt here.
int* test() { int a = 100; return &a; //After this function, the address has been destroyed, that is, the permission has been withdrawn } int main() { int* p = test();//p is the wild pointer //Although the address of a is accepted, the address of a does not belong to the test function //Therefore, the address to access a does not belong to a //That is, the accessed space does not belong to the current program //p becomes a wild pointer printf("hehe\n"); printf("%d\n", *p);//It doesn't print 100 return 0; }
2. How to avoid wild pointer
(1) Pointer initialization
(2) Be careful that the pointer is out of range
(3) The pointer points to space release and is set to NULL
(4) Avoid returning the address of a local variable
(5) Check the validity of the pointer before use
#include <stdio.h> int main() { int *p = NULL; //Initialize to null pointer //Null pointers cannot be accessed int a = 10; p = &a; if(p != NULL)//Check the validity. Null pointer is not accessed, and null pointer is not accessed { *p = 20; } return 0; }
4, Pointer operation
- Pointer+- integer
- Pointer pointer
- Relational operation of pointer
one Pointer + - integer
#define N_VALUES 5 float values[N_VALUES]; float *vp; //Pointer + - integer; Relational operation of pointer for (vp = &values[0]; vp < &values[N_VALUES];) { *vp++ = 0;//First assign a value, and then go one memory unit ahead of the address }
2. Pointer - pointer
Premise: two pointers point to the same space
int my_strlen(char *s) { char *p = s; while(*p != '\0' ) p++; return p-s;//The absolute value of subtracting two addresses is the number of elements between two addresses }
//Example, find the string length int my_strlen(char * s) { char* start = s; while(* s != '\0') { s++; } return s - start; } int main() { char arr[] = "abc"; int len = my_strlen(arr); printf("%d\n", len); return 0; }
3. Pointer relation operation
#define N_VALUES 5 float values[N_VALUES]; float *vp; for(vp = &values[N_VALUES]; vp > &values[0];) { *--vp = 0; }
Code simplification, which modifies the code as follows:
#define N_VALUES 5 float values[N_VALUES]; float *vp; for(vp = &values[N_VALUES-1]; vp >= &values[0];vp--) { *vp = 0; }
In fact, most compilers can successfully complete the task, but we should avoid writing this, because the standard does not guarantee its feasibility.
Standard provisions:
A pointer to an array element is allowed to be compared with a pointer to the memory location after the last element of the array, but it is not allowed to be compared with a pointer to the memory location before the first element.
5, Pointers and arrays
Let's take an example:
#include <stdio.h> int main() { int arr[10] = {1,2,3,4,5,6,7,8,9,0}; printf("%p\n", arr); printf("%p\n", &arr[0]); return 0; }
Operation results:
It can be seen that the array name and the address of the first element of the array are the same.
Conclusion: the array name represents the address of the first element of the array. (except for two cases, the previous array has been mentioned)
Then it is feasible to write code like this:
int arr[10] = {1,2,3,4,5,6,7,8,9,0}; int *p = arr;//p stores the address of the first element of the array
Since the array name can be stored as an address in a pointer, it is possible for us to use the pointer to access one.
For example:
#include <stdio.h> int main() { int arr[] = {1,2,3,4,5,6,7,8,9,0}; int *p = arr; //Pointer to the address of the first element of the array int sz = sizeof(arr)/sizeof(arr[0]); for(i=0; i<sz; i++) { printf("&arr[%d] = %p <====> p+%d = %p\n", i, &arr[i], i, p+i); //Even arr[i] can be written as p[i], and the effect is the same as arr[i] //p[i] --> * (p + i) --> arr[i] } return 0; }
Operation results:
So p+i actually calculates the address of array arr subscript i.
Then we can access the array directly through the pointer.
As follows:
int main() { int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; int *p = arr; //Pointer to the address of the first element of the array int sz = sizeof(arr) / sizeof(arr[0]); int i = 0; for (i = 0; i<sz; i++) { printf("%d ", *(p + i)); } return 0; }
6, Secondary pointer
Pointer variable is also a variable. If it is a variable, it has an address. Where is the address of pointer variable stored?
This is the secondary pointer.
The same is true for multi-level pointers.
For secondary pointers:
int* *ppa, * ppa indicates that this variable is a pointer variable, and int * is the type of the object pointed to, which is an integer pointer type.
The same is true for multi-level pointers.
The operations of the secondary pointer are:
- *ppa finds pa by dereferencing the address in ppa, * ppa actually accesses PA
int b = 20; *ppa = &b;//Equivalent to PA = & B;
- **ppa first finds pa through * ppa, and then dereferences PA: * PA, it finds a
**ppa = 30; //Equivalent to * pa = 30; //Equivalent to a = 30;
7, Pointer array
Is a pointer array a pointer or an array?
Answer: array.
Is an array of pointers (i.e. addresses).
Array, we already know integer array, character array.
int arr1[5]; char arr2[6];
What about pointer arrays?
int a = 0; int b = 0; int c = 0; int* arr3[5] = {&a, &b, &c};//An array that holds integer pointers int i = 0; for (i = 0; i < 3; i++) //The first three pointers of the array can be accessed. Null pointers cannot be accessed { printf("%d ", *(arr3[i])); }
arr3 is an array that stores integer pointers. It has five elements, and each element is an integer pointer.
Incomplete initialization means that the remaining elements are NULL (i.e. 0) by default, and the first three elements are pointers with integer data type
The last two are null pointers whose data type is integer.
arr3 | int * |
int * | |
int * | |
int * | |
int * |
Integer pointer array