C language pointer array pointer traversal

Pointer array pointer traversal

Refer to the summary of knowledge about C language novices turning into monsters

1. All data in the computer must be put into memory, and different types of data occupy different spaces, such as int 4 bytes

char 1 byte

2. Pointer (address): Each byte in memory has its own address, or pointer

Demo output address:

1. #include <stdio.h>
2.
3. int main(){<!-- -->
4. int a = 100;
5. char str[20] = "c.biancheng.net";
6. printf("%#X, %#X\
", & amp;a, str);
7. return 0;
8. }

operation result:
0X28FF3C, 0X28FF10
%#X means output in hexadecimal format, prefixed with 0X. a is a variable used to store integers. You need to add & amp; in front to get its address;
str itself represents the first address of the string, no need to add & amp;. There is a control character %p in C language, which is specially used to output addresses in hexadecimal form. However, the output format of %p is not uniform. Some compilers have 0x prefix, and some do not.

Everything is an address

1. Data and code are stored in memory in binary form. The operating system will give it corresponding permissions, granting permissions to read and execute. The memory block is code, and what is given to read and write is data (also May only have read access).

2.CPU can only obtain code and data through addresses.

3. To read and write data, the CPU must know the address of the data in the memory. Ordinary variables and pointer variables are mnemonics for the address. Although
*p and a obtain the same data, but their running processes are slightly different: a only needs one operation to obtain the data, while *p needs two operations, adding an extra layer of “indirection”

4. Using pointers is to obtain data indirectly, and using variable names is to obtain data directly. The former is more expensive than the latter.

5. In addition to obtaining data in memory, pointers can also modify data in memory, for example:

1. #include <stdio.h>
2. 
3. int main(){<!-- -->
4. int a = 15, b = 99, c = 222;
5. int *p = & amp;a; //Define pointer variable
//Page 221
6. *p = b; //Modify data in memory through pointer variables
7. c = *p; //Get data on memory through pointer variable
8. printf("%d, %d, %d, %d\
", a, b, c, *p);
9. return 0;
10. }

operation result:
99, 99, 99, 99
*p represents the data in a, which is equivalent to a. You can assign another piece of data to it, or you can assign it to another variable. (occurring simultaneously)

6.* has different functions in different scenarios: can be used in the definition of pointer variables to indicate that this is a pointer variable to distinguish it from ordinary variables; when using pointer variables, add in front It means getting the data pointed to by the pointer, or it means the data itself pointed to by the pointer.

In other words, the * when defining pointer variables has completely different meanings than the * when using pointer variables. Take the following statement as an example:
1. int *p = & amp;a;
2. *p = 100;
The * in the first line of code is used to indicate that p is a pointer variable, and the * in the second line of code is used to obtain the data pointed to by the pointer.
It should be noted that * cannot be added when assigning a value to the pointer variable itself. Modify the above statement:
1. int *p;
2. p = &a;
3. *p = 100;
You cannot add * before p in the second line of code.

Pointer variables can also appear in any expression where ordinary variables can appear, for example:

  1. int x, y, *px = & amp;x, *py = & amp;y;
  2. y = *px + 5; //Indicates adding 5 to the content of x and assigning it to y. *px + 5 is equivalent to (*px) + 5
  3. y = + + *px; //Add 1 to the content of px and assign it to y. + + *px is equivalent to + + (*px)
  4. y = *px + + ; //Equivalent to y=(*px) + +
  5. py = px; //Assign the value of one pointer to another pointer

8.P218

Assume that the addresses of variables a, b, and c in memory are 0X1000, 0X2000, and 0X3000 respectively, then the addition operation c = a + b; will be converted into a form similar to the following:
0X3000 = (0X1000) + (0X2000);
( ) represents a value operation. The meaning of the entire expression is to take out the values at addresses 0X1000 and 0X2000, add them, and assign the added result to the memory at address 0X3000.

9. The essence is to replace the data in the address with a pointer. If a pointer is not used, it will be meaningless to use ordinary variables directly, and it cannot be completely implemented (skin change)

[Example] Exchange the values of two variables through pointers.
1. #include <stdio.h>
2.
3. int main(){<!-- -->
4. int a = 100, b = 999, temp;
5. int *pa = & amp;a, *pb = & amp;b;
6. printf("a=%d, b=%d\
", a, b);
7. /*****Start exchanging*****/
8. temp = *pa; //Save the value of a first
9. *pa = *pb; //Give the value of b to a
10. *pb = temp; //Then pass the saved value of a to b
11. /*****End exchange*****/
12. printf("a=%d, b=%d\
", a, b);
13. return 0;
14. }
operation result:
a=100, b=999
a=999, b=100
It can be seen from the running results that the values of a and b have been exchanged. It should be noted that the temporary variable temp is particularly important because *pa
= *pb; After the statement, the value of a will be overwritten by the value of b. If the value of a is not saved first, it will not be found later.

10. A puzzle, but you need to understand the context and learn to think

Puzzles about * and & amp;
Suppose there is a variable a of type int, and pa is a pointer to it. What do * & amp;a and & amp;*pa mean respectively?
* &a can be understood as (&a), &a means to get the address of variable a (equivalent to pa), (&a) means to get the data at this address (equivalent to pa) ), going around and back to the original point, ** &a is still equivalent to a.
& amp;*pa can be understood as & amp;(*pa), *pa means getting the data pointed to by pa (equivalent to a), & amp;(*pa) means the address of the data (equivalent to & amp;a ), so &*pa is equivalent to pa.

  1. The asterisk* has three main uses:
    1. Indicates multiplication, such as int a = 3, b = 5, c; c = a * b;, which is the easiest to understand.
    2. Indicates defining a pointer variable to distinguish it from ordinary variables, such as int a = 100; int *p = & amp;a;.

    3. Indicates that obtaining the data pointed to by the pointer is an indirect operation, such as int a, b, *p = & amp;a; *p = 100; b = *p;

//next 9.3 P359

12. Some operations on pointer variables, such as addition, subtraction, comparison, etc.

When we add or subtract pointers, it is not a simple matter of adding 1 to the address and moving the whole backward, but the pointer is offset from the beginning of the data.
Each time pa, pb, and pc increase by 1, their addresses increase by 4, 8, and 1 respectively, which happen to be int, double, and char types.
Length; when subtracting 2, the address is reduced by 8, 16, and 2 respectively, which is exactly 2 times the length of int, double, and char types.

All elements in the array are arranged continuously in memory. If a pointer points to an element in the array, then adding 1 means
Points to the next element, minus 1 to point to the previous element.

  • For pointer calculations 3 don’t! ! !

    Don’t try to get the address of the next variable via a pointer

    Don’t try to add or subtract pointers to ordinary variables

    You cannot perform multiplication, division, remainder and other operations on pointer variables. In addition to syntax errors, it has no practical meaning.

Array pointer

When defining an array, you must give the array name and array length. The array name can be thought of as a pointer, which points to the 0th element of the array. In C language, we call the address of the 0th element the first address of the array. Taking an integer array as an example, arr points to

The following example demonstrates how to traverse array elements using pointers:
1. #include <stdio.h>
2.
3. int main(){<!-- -->
4. int arr[] = {<!-- --> 99, 15, 100, 888, 252 };
5. int len = sizeof(arr) / sizeof(int); //Find the length of the array
6. int i;
7. for(i=0; i<len; i + + ){<!-- -->
8. printf("%d ", *(arr + i) ); //*(arr + i) is equivalent to arr[i]
9. }
10. printf("\
");
11. return 0;
12. }
operation result:
99 15 100 888 252

The 5th line of code is used to find the length of the array. sizeof(arr) will get the number of bytes occupied by the entire array. sizeof(int) will get the number of bytes occupied by an array element. The result of their division is the array contains The number of elements, that is, the length of the array.
In the 8th line of code, we use the expression *(arr + i). arr is the array name, pointing to the 0th element of the array, indicating the first address of the array, arr + i points to the i-th element of the array, *(arr + i) means taking the data of the i-th element, which is equivalent to arr[i].
arr is a pointer of type int**. Each time it adds 1, its value will increase by sizeof(int). When i is added, its value will increase by sizeof(int) * i.

Define a pointer to an array, for example:

1. int arr[] = {<!-- --> 99, 15, 100, 888, 252 };
2. int *p = arr;
  1. arr itself is a pointer (strictly speaking, it is converted to a pointer) and can be directly assigned to the pointer variable p. arr is the address of the 0th element of the array, so int *p = arr;

Can also write
int *p = &arr[0];. In other words, the three ways of writing arr, p, & arr[0] are equivalent. They all point to the 0th element of the array, or to the beginning of the array!

2. If a pointer points to an array; the array pointer does not point to a complete array, but to an element of the array. What type of array is the pointer? It should be the same type as the array; the array in the above example is of type int. The relative pointer p is also an int*.

3.Change the above code

1. #include <stdio.h>
2.
3. int main(){<!-- -->
4. int arr[] = {<!-- --> 99, 15, 100, 888, 252 };
5. int i, *p = arr, len = sizeof(arr) / sizeof(int);
6.
7. for(i=0; i<len; i + + ){<!-- -->
8. printf("%d ", *(p + i) );
9. }
10. printf("\
");
11. return 0;
12. }

An array is just a simple arrangement of array elements in memory, without start and end marks. Sizeof§ / sizeof(int) cannot be used when finding the length of the array, because p is just a pointer to the int type, and the compiler does not know that it points to Is it an integer or a series of integers (arrays), so sizeof§ obtains the number of bytes occupied by the pointer variable p itself, not the number of bytes occupied by the entire array.

13. If a pointer variable p points to the beginning of the array, then p + i points to the i-th element of the array; if p points to the n-th element of the array, then p + i points to the n + i-th element; No matter which element p points to in the array, p + 1 always points to the next element, and p-1 always points to the previous element.

//Let p point to the second element in the array:
1. #include <stdio.h>
2.
3. int main(){<!-- -->
4. int arr[] = {<!-- --> 99, 15, 100, 888, 252 };
5. int *p = & amp;arr[2]; //can also be written as int *p = arr + 2;
6.
7. printf("%d, %d, %d, %d, %d\
", *(p-2), *(p-1), *p, *(p + 1), *(p + 2) );
8. return 0;
9. }
operation result:
99, 15, 100, 888, 252

There are now two ways to access array elements, one is to use subscripts, and the other is to use pointers.

1) Use subscripts

That is, the array elements are accessed in the form of arr[i]. If p is a pointer to the array arr, then you can also access the array element using p[i], which is equivalent to arr[i].

2) Use pointers

That is, use the form *(p + i) to access array elements. In addition, the array name itself is also a pointer, and you can also use *(arr + i) to access array elements, which is equivalent to *(p + i).

14. Array names or array pointers can be used to access array elements using the above two methods.

 The difference between array name and array pointer:

        The array name is a constant and its value cannot be changed, while the array pointer is a variable (unless it is specifically specified to be a constant) and its value can be changed arbitrarily. In other words, the array name can only point to the beginning of the array, and the array pointer can first point to the beginning of the array, and then point to other elements.

15. Use the increment operator to traverse array elements:

1. #include <stdio.h>
2.
3. int main(){<!-- -->
4. int arr[] = {<!-- --> 99, 15, 100, 888, 252 };
5. int i, *p = arr, len = sizeof(arr) / sizeof(int);
6.
7. for(i=0; i<len; i + + ){<!-- -->
8. printf("%d ", *p + + );
9. }
10. printf("\
");
11. return 0;
12. }
operation result:
99 15 100 888 252

In the 8th line of code, *p + + should be understood as *(p + +). Each loop will change the value of p (p + + causes the value of p itself to increase) so that p points to the next array element. This statement cannot be written as *arr ++ because arr is a constant and arr ++ would change its value, which is obviously wrong

16. What do p + +, + + p, (*p) + + mean respectively?
1.*p + + is equivalent to (p + +), which means first obtain the value of the nth element, and then point p to the next element
2.
+ + p is equivalent to *( + + p). The + + p operation will be performed first, so that the value of p increases and points to the next element. Overall, it is equivalent to *(p + 1), so The value of the n + 1th array element will be obtained.
3.(*p) + + is very simple. It will first obtain the value of the nth element, and then add 1 to the value of the element. Suppose p points to the 0th element, and the value of the 0th element is 99. After executing this statement, the value of the 0th element will become 100.

1,null pointer

A null pointer can be equal to a pointer of any type. The variable value is NUL L, which is essentially ((void *) 0)

2. Bad pointer

Note: The pointer variable is NULL or has an unknown address, causing the program to terminate unexpectedly. One of the important causes of bugs in C language.

3. Note: For pointers of int type, even if one byte of data is enough, it still occupies four bytes. 0010 0000 0000 0000. The principles for other types of data are similar.

4. Pointers of type void * void * will crash if the pointer operation cannot be performed.

5. The important function of passing pointers is to avoid copying large data. Because the cost is high and efficiency is greatly reduced. For example 1kb etc.

Assigning a number to a pointer variable is not allowed

For example int *p; p=1000; *p= & amp;a; wrong assignment