An array is a collection of data of the same type that occupies a contiguous chunk of memory. A pointer is an address stored in memory that does not occupy contiguous memory. Let’s write a little test code
void fun(void) { int i; Int num [10] =,1,2,3,4,5,6,7,8,9 {0}; int *p; p = num; for(i=0; i<10; i++) { printf("%d ",num[i]); } printf("\r\n------------------------------\r\n"); for(i=0; i<10; i++) { printf("%d ",p[i]); } printf("\r\n"); } int main(void) { delay_init(); LED_Init(); uart_init(115200); fun(); while(1) { LED = 0; delay_ms(1000); LED = 1; delay_ms(1000); }}Copy the code
Define an integer array, then define a pointer, pass the first address of the array to the pointer, and print the contents of the array and pointer separately. The printed result is:
Observe Pointers and arrays in Keil’s step mode
By observing the variables, we can see that the value stored in pointer P is the first address of array num 0x2000072C.
When you pass an array to a pointer, you do not pass the entire array to the pointer, but only the first address of the array.
Go down and print out the address of each variable in the array, then print the array through the pointer, and observe the change of the storage address in the pointer.
for(i = 0; i < 10; i++)
{
printf("value: %d ===> addr: %#x\r\n", num[i], &num[i]);
}
printf("\r\n------------------------------\r\n");
for(i = 0; i < 10; i++)
{
printf("value: %d ---->addr:%#x\r\n", *p, p);
p++;
}
printf("\r\n");
Copy the code
When the print function is called *p, the output is the value in the array. When p++ is executed, the contents of p are incremented by 4, that is, the address in P is incremented by 1. Since the array is int and an int is 4 bytes, the value is incremented by 4 when the address is incremented. The serial port output is as follows:
We can see that when we operate on an array with a pointer, only one address is ever stored in the pointer variable P. When operating directly on p, the address stored in P will change, and the * P instruction can read the contents stored in the current address. So when manipulating arrays with Pointers, pay special attention to subscript control. What happens if 15 sets of data are printed with Pointers?
for(i = 0; i < 15; i++)
{
printf("value: %d ---->addr:%#x\r\n", *p, p);
p++;
}
Copy the code
We can see that when the loop is more than 10 times, the address of the pointer increases by one int byte each time, but the data stored in the address is already chaotic. Therefore, when using the pointer to manipulate the array, we should always pay attention to whether the address of the pointer p points to the data outside the array. Otherwise, a program exception may occur.
P ++, *p++, * (p++), (*p ++), (*p)++
printf(" ------------ p++ ------------ \r\n");
p = num;
printf("value: %d ---->addr:%#x\r\n", *p, p);
p++;
printf("value: %d ---->addr:%#x\r\n", *p, p);
printf(" ------------ *p++ ------------ \r\n");
p = num;
printf("value: %d ---->addr:%#x\r\n", *p, p);
*p++;
printf("value: %d ---->addr:%#x\r\n", *p, p);
printf(" ------------ *(p++) ------------ \r\n");
p = num;
printf("value: %d ---->addr:%#x\r\n", *p, p);
*(p++);
printf("value: %d ---->addr:%#x\r\n", *p, p);
printf(" ------------ (*p)++ ------------ \r\n");
p = num;
printf("value: %d ---->addr:%#x\r\n", *p, p);
(*p)++;
printf("value: %d ---->addr:%#x\r\n", *p, p);
Copy the code
Give the first address of the array to the pointer P, and then manipulate the pointer differently to see what the difference is in the output.
P++, *p++, and * (p++) all add an int to the address of the pointer and output 1.
The last operation (*p)++ outputs 1, but the address stored in the pointer remains the same.
Note When the ++ operation is performed in the preceding three methods, the operation is all the address value stored in the pointer P. The last method performs the ++ operation on the value to which the address is stored in the pointer P.
(*p)++; (*p) = 0x20000730; (*p = 0x20000730; And then you do 0++, which is you add 1 to the 0th element of the array and 0+1 gives you 1. The address in p is still the address of the 0th element in the array.
Let’s see what happens when we put ++ in front of p. We also test the same 4 ways ++p, ++ *p,
P * (+ +), + + (* p).
printf(" ------------ ++p ------------ \r\n");
p = num;
printf("value: %d ---->addr:%#x\r\n", *p, p);
++p;
printf("value: %d ---->addr:%#x\r\n", *p, p);
printf(" ------------ ++*p ------------ \r\n");
p = num;
printf("value: %d ---->addr:%#x\r\n", *p, p);
++*p;
printf("value: %d ---->addr:%#x\r\n", *p, p);
printf(" ------------ *(++p) ------------ \r\n");
p = num;
printf("value: %d ---->addr:%#x\r\n", *p, p);
*(++p);
printf("value: %d ---->addr:%#x\r\n", *p, p);
printf(" ------------ ++(*p) ------------ \r\n");
p = num;
printf("value: %d ---->addr:%#x\r\n", *p, p);
++(*p);
printf("value: %d ---->addr:%#x\r\n", *p, p);
Copy the code
The result is as follows
Before ++p, p stores the address of the 0th element in the array. After ++p, p stores the address of the first element in the array.
Before ++*p, p stores the address of the 0th element in the array. After ++*p, p still stores the address of the 0th element in the array. Note When ++*p is executed, *p is executed first. The value of the 0th element is retrieved, and then the ++ operation is performed to increment the value by 1. There is no operation address.
*(++p) before the execution, p stores the address of the 0th element in the array, after the execution of *(++p), p stores the address of the first element in the array. Why is the 0th element of the array output before the execution of *(++p) 1? Instead of zero, right? This is because ++*p has changed the value of the 0th element in the array from 0 to 1 while executing the above ++*p code.
Before ++(*p), p stores the address of the 0th element in the array. After ++(*p), p still stores the address of the 0th element in the array. Note When ++(*p) is executed, *p is executed first. The value of the 0th element is retrieved and the ++ operation is performed to increment the value by 1. There is no operation address. The value of the 0th element was already changed to 1 during the above execution, so the ++ operation changes the value to 2.
After the above operation, the values in the array are:
The value of the 0th element in the array changes from 0 to 2, leaving the rest of the array unchanged. The above experiment gives a clearer idea of how Pointers operate inside programs when they are used to manipulate arrays.
Let’s sort the array with Pointers
void fun(int *p, int len) { int i = 0, j = 0, tem = 0; for(i = 0; i < len - 1; i++) { for(j = 0; j < len - 1 - i; j++) { if(*(p + j) < * (p + j + 1)) { tem = *(p + j); *(p + j) = *(p + j + 1); *(p + j + 1) = tem; } } } } int main(void) { int i = 0; int num[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; delay_init(); LED_Init(); uart_init(115200); Printf (" before sort \r\n"); for(i = 0; i < 10; i++) { printf("%d ", num[i]); } fun(num, 10); Printf ("\r\n after \r\n"); for(i = 0; i < 10; i++) { printf("%d ", num[i]); } while(1) { LED = 0; delay_ms(1000); LED = 1; delay_ms(1000); }}Copy the code
The output is
When operated by pointer data, must change the pointer points to address first, and then take corresponding values such as current address * (p + j), p points to is the first address of the array, is the address of the zeroth element p + j represents the address to the address of the first j a element in the array, and then in no. *, which is corresponding to change address values. If I write it as
P plus j, so you take the address of the 0th element, and you add j to the value of the element. If this is a bit of a hassle, you can write *(p + j) as p[j]. Just use Pointers like arrays.
Then the code can be changed
void fun(int *p, int len) { int i = 0, j = 0, tem = 0; for(i = 0; i < len - 1; i++) { for(j = 0; j < len - 1 - i; j++) { if(p[j] < p[j+1]) { tem = p[j]; p[j] = p[j+1]; p[j+1] = tem; }}}}Copy the code
The reason why * (p + j) isn’t * p[j] is because [] doesn’t mean square brackets, it means subscript operations. [j] = num[j] = num[j] = num[j] = address [] Num [j] is the data stored at the first address offset by J. If * is added at this time, it means that the value stored at the address p[j] is treated as the address and the data stored at this address is retrieved. For example, if the result of p[5] is 5, the result of * p[5] is 0x00000005, which will cause the program to run incorrectly. Num [I] = *(num + I) So the code can be changed when you can print the array
Printf (" before sort \r\n"); for(i = 0; i < 10; i++) { printf("%d ", num[i]); } fun(num, 10); Printf ("\r\n after \r\n"); for(i = 0; i < 10; i++) { printf("%d ",*(num + i)); }Copy the code
The printed result is
Arrays are also Pointers, although they don’t have the “*” sign that indicates pointer manipulation. In fact, C still compiles arrays as Pointers.
So in the program, operations on arrays are address references, not value references.