1 Basic operations of pointer variables Basic operations
int a,*iptr,*jptr,*kptr; iptr = &a; jptr = iptr; *jptr = 100; kptr = NULL;
Diagram:
1.1 Own address and own space
A pointer variable is also a variable, corresponding to a piece of memory space, corresponding to a memory address, and the pointer name is its own address. How big is this empty memory space? A machine word length, 32-bit CPU and operating system is 32 bits, 4 bytes, and its value range is: 0x-0xFFFFFFFF. 64-bit CPU and operating system are 64 bits, 8 bytes, and its value range is: 0x-0xFFFFFFFFFFFFFFFF.
1.2 Own value, other address, other space
The value of the pointer variable is the address of the space it points to, and the size of the space pointed to by the address is the size of the type pointed to by the pointer variable.
1.3 Declaration and initialization
When a pointer variable is declared and not initialized, the pointer variable only obtains its own memory space, and its pointing has not been determined. At this time, it is illegal to dereference the pointer variable as an lvalue. If you want to use a pointer variable dereference as an lvalue, there are three ways:
int *ptr; int *ptr_2; int a = 1; ptr_2 = &a; // *ptr = 0; // illegal operation, the memory space it points to has not been determined ptr = &a; // ① rvalue is a variable address ptr = ptr_2; // ② rvalue is a pointer of the same type and has been initialized ptr = (int*)malloc(sizeof(int));// ③ rvalue is a memory allocation function that returns a void pointer *ptr = 0; // Legal operation, ptr has a certain point and memory space pointed to;
1.4 Transfer of pointer values between functions
The local variables defined in the function (funcForSpace() in the following example) (a in the following example) are stored on the stack frame of a function. When a function is executed, another function (stackFrame_reuse() in the following example) The space will be reused by stackFrame_reuse(), and the space used by a will no longer exist, so when a pointer variable points to the memory space of a local variable, its address value is not a valid value when passed to the calling function.
#include <stdio.h> void funcForSpace(int **iptr) { int a = 10; *iptr = &a; } void stackFrame_reuse() { int a[1024] = {0}; } int main() { int *pNew; funcForSpace(&pNew); printf("%d\n",*pNew); // 10. At this time, the stack frame has not been reused stackFrame_reuse(); printf("%d\n",*pNew); // -858993460, garbage value while(1); return 0; }
A chunk of heap memory can be allocated within funcForSpace() and passed to the calling function.
#include <stdio.h> #include <malloc.h> int g(int **iptr) { // When trying to modify the first-level pointer variable of the calling function, the parameter of the called function is a second-level pointer if ((*iptr = (int *)malloc(sizeof(int))) == NULL) return -1; } int main() { int *jptr; g(&jptr); *jptr = 10; printf("%d\n",*jptr); // 10 free(jptr); while(1); return 0; }
You can illustrate the transfer process of the above code pointer:
The following figure a represents the computer memory, and b represents the stack frame space opened on the stack when a function is called:
2 Pointer variables and array names
The array name will be converted to the address pointing to the first element of the array in a certain context to facilitate the arithmetic operation of the pointer, such as
#include <stdio.h> int main() { int a[5] = {0}; char b[20] = {0}; *(a+3) = 10; // a+3 refers to an offset of sizeof(int) bytes relative to address a *(b+3) = 'x'; // b+3 refers to the offset sizeof(char) bytes relative to address b printf("%d, %c\n",a[3],b[3]); // 10, x while(1); return 0; }
The offset details of the above code pointers can be shown graphically:
3 Pointer passing between the calling function and the called function
Look at the following code:
#include <stdio.h> void swap1(int x, int y) { int tmp; tmp = x; x = y; y = tmp; } void swap2(int *x, int *y) { int tmp; tmp = *x; *x = *y; *y = tmp; } void caller() { int a = 10; int b = 20; swap1(a,b); printf("%d %d\n",a,b); swap2(&a,&b); printf("%d %d\n",a,b); } int main() { caller(); return 0; }
The above code can be understood with the following diagram:
swap1 pass value:
swap2 address transfer (pointer transfer):
4 Arrays as function parameters
A two-dimensional array is an array of arrays, and an n-dimensional array is an array of n-1-dimensional arrays. Memory is a one-dimensional sequence of bytes. The so-called n-dimensional array is actually just a logical representation, and its physical structure is still one-dimensional linear.
An element of an n-dimensional array is an n-1-dimensional array. If a pointer is used to point to an n-dimensional array, the pointer type must have n-1-dimensional length information, also when it is used as a function parameter.
void g(int a[][2]) { // void g(int(*a)[2]){ is the same way of writing a[2][0] = 5; } void caller() { int a[3][2]; int (*p)[2] = a; *(*(p+2)+0) = 7; // p=2 means offset sizeof(*p) relative to address p printf("%d\n",a[2][0]); // 7 g(a); printf("%d\n",a[2][0]); // 5 }
The following code can be understood with the following diagram:
ref:
Kyle Loudon< Mastering Algorithms with C>