1, the introduction

Pointers are also memory addresses. Pointer variables are used to store memory addresses. Pointer variables of different types occupy the same storage unit length, while variables of different data types occupy different storage space lengths. With Pointers, you can manipulate not only the data itself, but also the address of the variable where the data is stored

All data on a computer must be stored in memory. Different types of data take up different numbers of bytes. For example, int takes up four bytes and char takes up one byte. In order to access the data correctly, each byte must be numbered. Just like a house number or a national identification number, each byte is numbered uniquely so that a specific byte can be identified by the number.

In a computer, all data is stored in memory, and different data types occupy different amounts of memory space. Memory is contiguous addressing space in bytes, and each byte unit corresponds to a unique number called the address of the memory unit. For example, int takes two bytes, char takes one byte, etc. Memory allocates the address of the first byte unit of storage for a variable, called the address of the variable. An address identifies a storage unit to facilitate data access. Addresses are figuratively called Pointers in high-level languages, and cpus need addresses to access memory, not variable and function names! Variable and function names are just mnemonics for addresses, and they will be replaced with addresses when the source file is compiled and linked into an executable program. An important part of the compilation and linking process is finding the addresses that these names correspond to.

Note that variable names and function names allow us to write code with English strings that are easy to read and understand, without having to deal directly with binary addresses. While variable names, function names, string names, and array names are essentially the same in that they are all mnemonics for addresses, when writing code we think of variable names as representing the data itself, while function names, string names, and array names represent the beginning address of a code block or data block.

A pointer, relative to a memory location, refers to the address of the location in which the data is stored. In C, pointer variables are allowed to store Pointers, so the value of a pointer variable is the address of a memory location or a pointer called a memory location.

2. Definition and use of Pointers

Pointers to variables and pointer variables:

In C, it is possible to store a pointer in a variable called a pointer variable. The value of a pointer variable is the address of a piece of data. Such a piece of data can be an array, a string, a function, or another ordinary variable or pointer variable

A pointer to a variable is the address where the variable is stored, and a pointer variable is the variable where the pointer is stored. A pointer variable is a variable that stores the address of a variable. Unlike other types of variables, it is specifically used to store the memory address. It is also called an address variable. The general form for defining a pointer variable is: Type specifier * variable name * Type specifier indicates the data type of the variable to which the pointer variable points; * indicates that this is a pointer variable; The variable name represents the name of the defined pointer variable, and its value is an address, for example: char * p1; P1 is a pointer variable whose value is the address of a character variable

// Defining a pointer variable is very similar to defining a normal variable, except that the variable name is preceded by an asterisk * in the format int *fp; //* indicates a pointer variable, fp is a pointer to intfloat*a,*b; // indicates that both a and b are Pointers to afloatA pointer to a data typeCopy the code

Pointer variable use:

Address fetch operator & : The unary & operator is used to fetch the address of the operation object. Example: &i is the address of variable I. Constant expressions and register variables cannot be addressed (because they are stored in memory and have no address). Pointer operator * (indirection) : The inverse operation with & is used to retrieve the stored contents by manipulating the address of the object. For example, x = &i x is the address of I, and *x is the address of I to obtain the content of I.

// assign int a = 100; Int *p_a = &a; // Initialize a pointer to p_a that points to a while defining the pointer variable p_a and assigning the address of a to it. Note that p_A needs an address, a must be preceded by the address &, otherwise it is not correct.Copy the code

Like normal variables, pointer variables can be written as many times as you like, and you can change the value of a pointer variable whenever you want:

// Define common variablesfloatA = 99.5, b = 10.6; char c =The '@', d = The '#'; // Define pointer variablesfloat*p1 = &a; Char *p2 = &c; // change pointer variable p1 = &b; // change p1 to b; // change p2 to point to aCopy the code
  • * is a special symbol that indicates that a variable is a pointer variable and must be marked with * when p1 and p2 are defined. For p1, p2, assignment, because already know it is a pointer variable, just don’t have to reinvent the wheel with a *, behind can be used as common variable to use pointer variable. That is, pointer variables must be defined with *, and pointer variables cannot be assigned with *.

Int *p; int *p; p = &a; *p = 100; Or: int b=200; int *a; a=b; // This is also an error, because there is no fetch &Copy the code

The pointer variable stores the address of the data. The address of the data can be obtained through the pointer variable:

#include <stdio.h>
int main(){
    int a = 66;// Define an integer variable
    int *p = &a; // Define a pointer to int and point to the address of a
    printf("%d, %d\n", a, *p);  // The value of a can be printed in either way
    return 0;
}

*p = 0X1000 *p = 0X1000 *p = 0X1000 *p = 0X1000 *p = 0X1000That's the value of variable A. So from the running result, *p is equivalent to a. CPU to read and write data must want to know the data in the memory address, ordinary and pointer variables are address mnemonics, although by * p and a access to the data, but their operation process is slightly different: a only need an operation will be able to obtain data, and * p after two operations, more than a layer of "indirect".// After the program is compiled and linked, a and p are replaced with the corresponding addresses. To use *p, obtain the value of variable P itself through address 0XF0A0.This value is the address of variable A, and then it's going to get the data from variable A that is to say, it's going to be more expensive to get the data indirectly using a pointer than it is to get the data directly using a variable name.Copy the code

A pointer can be used to change the value of the variable to which it is referred, for example:

#include <stdio.h>int main(void){ int a = 1, b = 66, c = 2; Int *p = &a; // define a pointer variable and point to a *p = b; C = *p; c = *p; c = *p; // Assign the value of pointer p to C.printf("%d, %d, %d, %d\n", a, b, c, *p); // So they all have the same valuereturn0; } * can be used in the definition of a pointer variable to indicate that it is a pointer variable to distinguish it from a normal variable; When we use pointer variables, we use * to get the data that the pointer points to, or the data that the pointer points to itself.Copy the code

That is, the * when defining pointer variables has a completely different meaning than the * when using pointer variables. Take the following statement as an example:

int *p = &a; *p = 100; // Get the data to which the pointer pointsCopy the code

Some other operations:

int x, y, *px = &x, *py = &y; y = *px + 5; *px+5 = (*px)+5 y = ++*px; ++*px = *px++; // y=(*px)+ py = px; // Assign the value of one pointer to another pointerCopy the code

About ampersand and *

Both ampersand and * are right-sided. Given a variable x = 10, *&x means that the address of variable x is first retrieved, and then the contents of the address are retrieved. Because ampersand and * are the inverse of each other, x = *&x.

Suppose we have a variable a of type int and pa is a pointer to a. What are the meanings of *&a and &*pa respectively?

*&a can be understood as *(&a), which means to take the address of variable A (equivalent to Pa), and *(&a) which means to take the data at that address (equivalent to Pa), and go around and around and get back to the origin, and *&a is still equivalent to A.

&*pa can be understood as &(*pa), * PA means to get the data to which PA points (equivalent to a), &(*pa) represents the address of the data (equivalent to &a), so &*pa is equivalent to PA.

Wild and null Pointers

A null pointer means that the pointer does not point to a meaningful chunk of memory, for example :char* k; This k right here is called a null pointer. We’re not pointing it to any arbitrary point. Or char* k = NULL; This k here is also called a NULL pointer because it points to NULL, which is 0, the integer 0, not ‘\0’ and a NULL pointer can’t be fetched, a NULL pointer can only be fetched if it actually points to a meaningful chunk of memory. So k = “Hello world!” ; Then k is not a null pointer.

For NULL pointer values, the general documentation tends to use NULL instead of saying 0 directly. But we should be clear: returning NULL and returning 0 are exactly the same for pointer types, because both NULL and 0 represent “NULL pointer”. A null pointer is a pointer that is assigned a value of 0 until it is initialized.

Such as:

int *a; // define a pointer a=NULL; // set the pointer to null a =0; // This is also the way to make a pointer point to nullCopy the code

Note: void* is not called a null pointer, it is called an indeterminate pointer. This pointer points to a chunk of memory without telling the program how to interpret it. Therefore, this type of pointer cannot directly fetch the contents of the operation. A pointer of another type must be converted before the content can be interpreted. ‘\0’ is a pointer to the end of a string. Void * is a pointer to a string that does not know what to point to.

The null pointer refers to a pointer whose value is null, while the value of the wild pointer is not null. The wild pointer points to a segment of actual memory, but we do not know where it points to, or the memory space it points to has been freed, so in the actual use process, We cannot tell whether a pointer is wild by nulling the pointer. Avoiding wild Pointers is up to us to develop good programming habits

Wild pointer is a pointer to the location is unknown (random, not correct, there is no clear limit) if when defined uninitialized pointer variable, its value is random, pointer variable’s value is the address of the other variable, means that the pointer to an address is uncertain variables, the reference to solution is to go to a visit to an uncertain address, So the result is unknowable. (Baidu explanation)

Here’s what can happen to wild Pointers and how to avoid them.

1, pointer variable value is not initialized: when a pointer is declared, it is not initialized explicitly, then the address space to which the pointer points is arbitrarily pointed. If the pointer is declared in the global data area, the uninitialized pointer defaults to null. If the pointer is declared in the stack area, the pointer points to an arbitrary address space. So good programming practice is to initialize a pointer as soon as it is declared, and if you don’t know what value to initialize it to, null the pointer first.

int main(void){ int *a; / / wild pointerif(a! =NULL){ .... } /* int *a; a=NULL/0; Correct reference */}Copy the code

The address space to which the pointer points has been free or deleted: If the malloc or new address space on the heap is already free or deleted, then the memory on the heap has been freed. But if the pointer to the memory has not been modified, then the pointer will continue to point to the memory on the heap that has been freed. Therefore, it is a good programming practice to empty the pointer to memory immediately after it is free or delete.

void func() { int *ptr = new int[5]; delete [ ]ptr; PTR =NULL; PTR =NULL; PTR =NULL; Correct}Copy the code

3. Pointer manipulation goes beyond scope. If you have a pointer in a block that points to a variable in that block, but that variable is only valid in that block, then the variable is invalid and the pointer to it becomes a wild pointer

void func() { int *ptr = nullptr; { int a = 10; ptr = &a; } int b = * PTR; PTR =NULL; PTR =NULL; Correct}Copy the code

When using Pointers, avoid: NULL for initialization and NULL for release

3. Pointer operation

A C pointer is a numeric address. Therefore, you can perform arithmetic operations on Pointers. Four arithmetic operations can be performed on Pointers: ++, –, +, and -. Incrementing decrement adding and subtracting, two Pointers subtracting

#include<stdio.h>
int main(void) {
	int a=10; 
	int *pa = &a,*pA=&a;

	double b = 22.2;
	double *pb = &b;

	char c = 'C'; char *pc = &c; // The initial valueprintf("1- %#x %#x %#x \n", &a, &b, &c); / / %#x means convert to hexadecimal tape format to output the address,// The effect is to add 0x before the outputprintf("2- %#x %#x %#x \n", pa, pb, pc);

	//指针加法
	pa += 2; pb += 2; pc += 2;
	printf("3- %#x %#x %#x \n", pa, pb, pc); // pa -= 2; pb -= 2; pc -= 2;printf("4- %#x %#x %#x\n", pa, pb, pc); // Compare Pointersif (pa == pA) {
		printf("5=%d\n", *pA);

	}
	else {
		printf("6=%d\n", *pa);
	}

	return0; } / / can be seen from the result: pa, pb, PC + 1 at a time, they add 4, 8, 1 address respectively, is precisely the int, double, char types of length; When we subtract 2, we decrease the address by 8, 16, and 2, respectively. This is exactly twice the length of an int, double, and char. /* Each increment of a pointer points to the next element's location. Each time the pointer decays, it points to the storage location of the previous element. The number of bytes a pointer jumps when incrementing or decrementing depends on the length of the data type of the variable to which the pointer points, such as int, which is 4 bytes. Pointer variables can participate in addition to addition and subtraction operations, can also participate in comparison operations. When you compare a pointer variable, you compare the value of the pointer variable itself, which is the address of the data. If the addresses are equal, the two Pointers point to the same piece of data, otherwise they point to different pieces of data. Of course, there are other logical operators. The code above (first example) compares pa and PA, pa already refers to the last data of A, so they are not equal. And I don't know what the last data of A was, so it will lead toprintfDo not add or subtract a pointer to a normal variable. Note: you cannot multiply, divide, or mod a pointer variable. It has no practical meaning except syntax errors.Copy the code
#include
      
       // Add and subtract the pointer to the address on the move
      Int main(void) {char a[] = {2,3,4,5,6}; char *p = &a[0]; char *p1 = &a[10];printf("p1-p=%d\n", p1 - p);
	printf("p=%p\n", p);
	printf("p1=%p\n", p1); Int *t = a[0]; int *t = a[0]; int *k = a[3];printf("* %d\n", t-k); Int b[] = {1,2,3,4,5,6}; int *q = &b[0]; int *q1 = &b[6];printf("q1-q=%d\n", q1 - q);
	printf("%p\n", q1);
	printf("%p\n", q);

	return 0;
}Copy the code

Common pointer operation: * (++ P) : first move the pointer, take the value of the next cell * (p++) : first remove the value of the current cell, then move the pointer (* p) ++ : first remove the value of the current cell, then make the current cell value + 1 (pointer does not move) ++ (* p) : Incrementing the value of the current cell by 1 before fetching the value of the current cell (pointer does not move)

Pointer conversion: int *p=&i; void *q=(void * )p; It doesn’t change the type of variable that p refers to, but it allows people to look at the variable that p refers to in a different way: p here I don’t treat you as an int anymore, I treat you as a void

Note that *p++ and * (p++) are equivalent due to priority issues

Int I,printf(“%x”,&i); Get the address of I and print it. int i,printf(“%p”,&i); Get the address of I and print it. Whether an address is the same size as int depends on the compiler

Note the type of pointer. All Pointers are of the same size no matter what type they point to because they are addresses, but Pointers to different types cannot be assigned to each other to avoid using the wrong pointer.

Strings and Pointers, arrays and Pointers

  • When you define an array, you give the name and length of the array. The name can be thought of as a pointer to the 0th element of the array. In C, we will address the zeroth element is called the first address of the array, the array name was meant to say the entire array, which is said more than a collection of data, but in the use process will often into a pointer to an array element 0, so I use the word “think”, said an array name and address of the first array is not always equivalent.

#include<stdio.h>Int main(void) {int a[] = {1,2,3,4,5,6}; int line = sizeof(a) / sizeof(a[0]); // Calculate the length of the array int I;for (i = 0; i < line; i++) {

		printf("%d ", *(a + i)); // *(a + I) = a[I]}return0; } We use the expression *(a+ I), where a is the name of the array, refers to the 0th element of the array, represents the address of the array, a+ I refers to the ith element, and *(a+ I) represents the data of the ith element, which is equivalent to a[I].Copy the code

We can also define a pointer to an array, for example:

Int a [] = {6}; int *p=a; A is itself a pointer that can be assigned directly to the pointer variable P. A is the address of the 0th element of the array, so int *p = a; Int *p = &a[0]; . That is, a, p, &a[0] are all equivalent; they all refer to the 0th element of the array, or to the beginning of the array. * If a Pointer points to an Array, we call it an Array Pointer. * If a Pointer points to an Array, we call it an Array Pointer.Copy the code

An array pointer points to an element in the array, not the entire array, so the type of the array pointer depends on the type of the array element. In the above example, p points to an element of type int, so p must also be of type int *. On the other hand, P doesn’t know that it points to an array, p only knows that it points to an integer, and how to use p depends on the programmer’s code.

An array in memory is just a simple arrangement of its elements, with no beginning and end flags, and you can’t use p to sizeof(p)/sizeof(int) to figure out the length of an array, because P is just a pointer to an int, The compiler does not know whether it refers to an integer or a series of integers (arrays), so sizeof(p) evaluates the number of bytes taken up by the pointer variable p itself, not the entire array. If you do not know the length of the array, you cannot traverse the entire array

With the introduction of Pointers, there are two ways to access array elements: one is to use subscripts, and the other is to use Pointers: 1. If p is a pointer to array arr, then array elements can also be accessed using p[I], which is equivalent to arr[I].

Using Pointers means accessing an array element with the form *(p+ I). You can also use *(arr+ I) to access array elements, which is equivalent to *(p+ I).

The above two methods can be used to access array elements, whether they are array names or array Pointers. The difference is that array names are constants and their values cannot be changed, whereas array Pointers are variables (unless they are specified as constants) and their values and points to can be changed at will. That is, the array name can only point to the beginning of the array, and the array pointer can point to the beginning of the array before pointing to any other element.

// Use increment to iterate over the array#include<stdio.h>Int main(void) {int a[] = {1,2,3,4,5,6}; int line = sizeof(a) / sizeof(a[0]); int i; int *p = a; // the pointer p points to the beginning of the arrayfor (i = 0; i < line; i++) {

		printf("Address a[%d] : %p\n",i,p);
		printf("Value [% d] a: % d \ n", i, *p); // pointer increment move p++; }return0; } /* decrement is the same effect increment decrement needs to pay attention to: *p++; Int b[] = a; int b[] = a; int b[] = a; //int *p = a; // b = a; //int b[] = -- > const b; Because const means that the b constant cannot be changedCopy the code

Const int a[]={1,2,3,4,5,6}; The array variable is already a pointer to const, so const means that each unit of the array is a const int and must be assigned by initialization.

Int a[10]; int a[10]; Int b==&a[0]; int b==&a[0]; The [] operator can do things to arrays as well as Pointers: p[0]=a[0];

  • There is no specific string type in C. We usually put strings in an array of characters, so a character array is still an array. The same rules about Pointers and arrays that we learned in the previous section apply to character arrays. Change the above code to print the string as a pointer:

#include<stdio.h>
#include<stdlib.h>

int main(void) {
	char s[] = "hello world"; char *p = s; int len = strlen(s); // Get the string length function int I; // Use a pointer to iterate over the string outputfor (i = 0; i < len; i++) {
		printf("%c", *(p + i));
	}
	printf("\n"); // use an array to iterate over the outputfor (i = 0; i < len; i++) {
		printf("%c", p[i]);
	}
	printf("\n"); // Use pointer outputfor (i = 0; i < len; i++) {
		printf("%c", *(s + i));
	}

	printf("\n");
	return 0;

}Copy the code

In addition to character arrays, C supports another way of representing strings, which is to use a pointer to the string directly, for example:

char *str;
str = "hello world"; /* The string pointer points to a string, and STR is a char pointer to a string"hello world"The pointer variable STR holds the first address of the string. So the output is a string, which should be rewritten asprintf(" % s \ n ", STR);Copy the code

All characters in a string are sequentially arranged in memory. STR points to the 0th character of the string (an array of characters). We usually refer to the address of the 0th character as the beginning of the string. Each character in a string is of type CHAR, so STR must also be of type char *.

It all looks and character array is how similar, output the string, they can use % s * or [] can be used to obtain a single character, the difference between these two approaches are as follows: they are the most fundamental difference is that in memory storage area is different, character array data stored in the global area or stack area, the second kind of string is stored in the constant area. Strings in the global data area and stack area (including other data) have read and write permissions, while strings in the constant area (including other data) have only read permissions, but not write permissions. An obvious consequence of the different memory permissions is that a character array can read and modify each character once it is defined, whereas a string of the second form, once defined, can only be read and cannot be modified, and any assignment to it is an error.

We call the second form of a string a string constant, which means that constants can only be read but not written:

    char *str = "Hello World!"; // the character constant is the pointer STR ="I love C!"; // Correctly repoint the constant string pointer to the string STR [3] ='P'; // Error this is trying to assign a character array through a character constant pointerCopy the code

This code compiles and links normally, but runs with Segment faults or incorrect write positions. Line 2 is correct to change the pointing of the pointer variable itself; Line 3 is wrong and cannot modify characters in a string.

Is it a character array or a string constant pointer? If the programming process only involves the reading of the string, then the character array and string constants can meet the requirements; If there are write (modify) operations, you can only use character arrays, not string constants.

To summarize, C has two ways of representing strings: character arrays and string constants (Pointers), which are stored in different locations in memory so that character arrays can be read and modified, whereas string constants (Pointers) can only be read and cannot be modified.

5, Pointers to function parameters, Pointers to function return types

Sometimes we can use the return value of a function to send data back and forth. This is fine in simple cases, but not if the return value has another purpose (such as returning the amount of execution state of the function) or if more than one data is being sent back. So you want to refer to a pointer to pass

Pointer to function arguments:

In C language, function parameters can not only be integers, decimals, characters and other specific data, but also can be Pointers to them. Using a pointer variable as a function parameter can pass the address outside the function to the inside of the function, so that the data outside the function can be accessed from inside the function without being destroyed at the end of the function. Arrays, strings, dynamically allocated memory, etc., are collections of data. There is no way to pass all of them into a function through a single parameter. We can only pass Pointers to them and influence the data set through Pointers inside the function. In some cases, Pointers are also required to operate on primitive types such as integers, decimals, and characters. A typical example is swapping the values of two variables:

#include <stdio.h>void swap(int a, int b){ int temp; // temp = a; a = b; b = temp; } intmain(){
    int a = 66, b = 99;
    swap(a, b);
    printf("a = %d, b = %d\n", a, b);
    return0; } /* From the result, it can be seen that the values of a and B do not change, and the exchange fails. This is because a and B inside swap() and a and B inside main() are different variables that occupy different amounts of memory. They have no relationship other than their names. Swap () swaps a and B inside. Does not affect the values of a and b outside of main(). They lose scope as the function segment endsCopy the code

Using Pointers:

#include <stdio.h>Void swap(int *p1, int *p2){// temp = *p1; *p1 = *p2; *p2 = temp; } intmain(){ int a = 66, b = 99; swap(&a, &b); // The addresses of a and B are passed inprintf("a = %d, b = %d\n", a, b);
    return0; } // After the function is executed, p1 and p2 will be destroyed, but its impact on external A and B is "persistent" and will not be "restored" with the end of the function. Because what we're doing to it is going into the addressCopy the code

Use arrays as function arguments:

If a function passes an array by value, it must allocate enough space to store a copy of the original array and then copy all of the original arrays into the new array. It is more efficient to pass the address of the array to the function and let the function process the original array directly. But the delivery address, will lead to some problems, C transfer data value, usually because it can guarantee the integrity of the data, if the function is using a copy of the original array, modifying the original data will happen, but usually need to use the original data processing of the array function, so this function can modify the original array, sometimes, Void add(double a[],int n,int b); Call this function to modify the value of the original array, or to modify the original array directly through a pointer

An array is a collection of data that cannot be passed inside a function by arguments at once. If you want to manipulate an array inside a function, you must pass an array pointer. The following example defines a function Max () to find the element with the largest value in an array:

#include<stdio.h>int max(int len, int a[]); Int a[100] and int a[] do not create an array. The compiler does not allocate memory for them. The actual array does not exist. They will eventually be converted to Pointers like int *intArr. This means that neither form can pass in all the elements of the array at once, and you have to be disciplined about using array Pointers. */ // True arrays can have fewer or more than 100 elements. int main(void) { int n; int a[100]; int i; scanf("%d", &n);
	for (i = 0; i < n; i++) {
		scanf("%d", a+i); } // The prototype of the a is int *a // so you can use &a[I] or a+ Iprintf("max=%d", max(n,&a));
	return0; } int Max (int len, int a[]) {int t = a[0]; int i;for(i = 1; i < len; I++) {// compare in sequenceif(t < a[i]) { t = a[i]; }}returnt; Note that no matter how you pass an array, you cannot get the length of the array inside the function because intArr is just a pointer, not a real array, so you must add an extra argument to pass the length of the array. Const int sum (const int a[],int b); const int sum (const int a[],int b); const int sum (const int a[],int b);Copy the code

Why doesn’t C allow all elements of an array to be passed directly, instead of having to pass Pointers to arrays? The passing of parameters is essentially an assignment, which is a copy of memory. Memory copy refers to copying data from one memory to another.

For data of basic types such as ints, they tend to take up only a few bytes of memory, making memory copies of them very fast. And array is a series of data collection, there is no limit to the amount of data, may have little, may also have thousands of, they are memory copy is likely to be a long process, will be seriously slow down the efficiency of the program, in order to prevent poor skills of programmers write inefficient code, C language not syntactically support direct assignment of data collection.

Pointer function return type: after the program is compiled, each function has the address to execute the first instruction, that is, the first address, called [function pointer. Function pointer is a pointer variable to the function, to indirectly call the function can use the pointer variable to achieve.

Int (* pf) (int, int).

By forcibly combining PF with the “*” in parentheses, pf is defined as a pointer, and then again with the “()” below to indicate that the pointer points to a function, which is represented in parentheses as a parameter of type int, and finally with the previous int, where int represents the return value of that function. Thus, PF is a pointer to a function that returns an int. Function Pointers have very different meanings from functions that return Pointers. A function pointer is itself a pointer to a function. A pointer function is itself a function that returns a pointer.

#include<stdio.h>
#include<stdlib.h>char *strs(char *strl1, char *strl2); Int main(void) {char str1[50]; // Define the string char str2[50]; char *str; // define the character pointer gets(str1); / / input gets (str2); str = strs(str1, str2);printf("%s", str);

	return 0;

}
char *strs(char *strl1, char *strl2) {

	if(strlen(strl1) > strlen(strl2))return strl1;
	}
	else {
		returnstrl2; }}Copy the code

When using a pointer as a function return value to note is that after the function will destroy all of the local data defined in its interior, including local variables, local array and formal parameters, the function returns a pointer to the please try not to point to these data, the C language there is no mechanism to ensure that these data will always be valid, Them in the subsequent use process may result in a runtime error, but the destruction in the sense that there is not memory wipe out all the local data, but give up to its access, abandoned ignore, the back of the code can use the memory, if you use will also be able to get the correct data in time, If any other function is called it will overwrite the memory and the resulting data will be meaningless. There’s no way of knowing what kind of data is covering it (it’s usually a meaningless or even weird value).

#include <stdio.h>
int *func(){
    int n = 100;
    return &n;
}
int main(){
    int *p = func(), n;
    n = *p;
    printf("value = %d\n", n); // Since there is no overwrite, we still get the previous valuereturn0; } ****** is compared with: ******#include <stdio.h>
int *func(){
    int n = 100;
    return &n;
}
int main(){
    int *p = func(), n;
    printf("c.biancheng.net\n"); // this will cover n = *p;printf("value = %d\n", n); // The output value will not be knownreturn 0;
}Copy the code

You should also pay attention to calls to function pointer variables:

Parsing function pointer variables cannot perform arithmetic operations, unlike array pointer variables. An array pointer variable can be added or subtracted by an integer to cause the pointer to move to a later or array element, whereas a function pointer move is meaningless. The parentheses surrounding the “(* pointer variable name)” in a function call are indispensable. The “*” should not be understood as an evaluation operation, but as a notation. “Z = * pomax(x,y);” To “z = (* pomax) (x, y);” .

6. Secondary pointer (multi-level pointer)

As a variable, the pointer variable also has its own storage address, and the storage address pointing to the pointer variable is called the pointer of the pointer, that is, the secondary pointer. Superimposed in turn, the formation of multi-level Pointers. Pointers can point to a common type of data, such as int, double, char, etc., or to a pointer type of data, such as int *, double *, char *, etc. If a pointer points to another pointer, we call it a second-order pointer, or a pointer to a pointer. , let’s first look at the second-level pointer, their relationship is as follows:

int a =100; // a common variable int *p1 = &a; Int **p2 = &p1; // p2 -> P1 -> a // &p1&a 100 /* Rule: level-1 pointer points to the address of a variable. Level-2 pointer points to the address of level-1 pointer. Level-2 pointer points to the address of level-2 pointerCopy the code

A pointer variable is also a variable that takes up storage. You can also use & to get its address. C language does not limit the level of pointer, each increase in the level of pointer, in the definition of pointer variable must add an asterisk *. P1 is a first-level pointer to a common type of data, defined with a *; P2 is the second-level pointer to the first-level pointer P1, and is defined with two *.

Multilevel Pointers are:

int ***p3 = &p2; // int ****p4 = &p3; Int *****p5 = &p4; // Level 1 and level 2 Pointers are often used in development, but advanced Pointers are rarely used.Copy the code

If we want to get the data to which the pointer points, we add one * to the first pointer, two * to the second pointer, and three * to the third pointer as follows:

#include <stdio.h>
int main() {

	int a = 100;
	int *p1 = &a;
	int **p2 = &p1;
	int ***p3 = &p2;

	printf("%d, %d, %d, %d\n", a, *p1, **p2, ***p3); // They all have the same valueprintf("&p2 = %#X, p3 = %#X\n", &p2, p3); // It points to the same addressprintf("&p1 = %#X, p2 = %#X, *p3 = %#X\n", &p1, p2, *p3);
	printf(" &a = %#X, p1 = %#X, *p2 = %#X, **p3 = %#X\n", &a, p1, *p2, **p3);

	return0; } // Use the third level pointer p3 as an example to analyze the above code. ***p3 is equivalent to *(*(*p3)). *p3 yields the value of p2, which is the address of P1; *(*p3) yields the value of p1, which is the address of A; After three value operations, *(*(*p3)) is the value of A.Copy the code

7, pointer arrays, Pointers to functions, Pointers to two-dimensional arrays

Pointer array:

Pointer variables, like ordinary variables, can form arrays. If all the elements in an array hold Pointers, we call it a pointer array. Pointer arrays are typically defined as:

Data type * name [array length]; Int *a [10]; A is an array containing 10 elements, each of which is of type int *.Copy the code

Pointer arrays are the same as regular arrays except that each element has a different data type. Here’s a simple example:

#include<stdio.h>int main(void) { int a = 1; int b = 2; int c = 3; Int *an[3] = {&a,&b,&c}; Int **p = an; int **p = an; int **p = an; // The array itself represents an address, so do not fetch the address character &printf("%d %d %d\n", *an[0], *an[1], *an[2]);
	printf("%d %d %d\n", **(p + 0) , **(p + 1), **(p + 2));

	return0; } // ArR is an array of Pointers. It contains three elements, each of which is a pointer. When we define arR, we initialize it with the addresses of variables A, B, and c, just like an array. Parr is a pointer to the array arr, specifically to the 0th element of arR. It should be defined as int *(*parr). The * in parentheses indicates that parr is a pointer, and the int * outside the parentheses indicates the type of data parr points to. The 0th element of arr is of type int *, so we define parr with two *.Copy the code

Pointer arrays can also be used with string arrays:

#include <stdio.h>
int main(){char * STR [3] = {// Define an array of strings of length 3"c.biancheng.net"."C Language Chinese website"."C Language"
    };

    printf("%s\n%s\n%s\n", str[0], str[1], str[2]); // Prints each string in turnreturn 0;
}Copy the code

Pointer to a function:

A function occupies a contiguously large area of memory. Function names in expressions are sometimes converted to the first address of the memory area in which the function resides, much like array names. We can assign the start address (or entry address) of the function to a pointer variable that points to the memory region where the function is located, and then use the pointer variable to find and call the function. Such Pointers are function Pointers.

Data type * Pointer name (data type parameter); The data is the function return value type, the pointer name, and the function argument list in parentheses. A parameter list can give both the type and the name of the parameter, or it can give only the type of the parameter and omit the name of the parameter, much like a function prototype.Copy the code

Note that () takes precedence over *, and the first parenthesis cannot be omitted if returnType *pointerName(param list) is written; This is the function prototype, which indicates that the function returns a value of type returnType *

To call a function with a pointer:

#include <stdio.h>Int Max (int a, int b){returna>b ? a : b; } int main(void){ int x, y, maxval; *pmax int (*pmax)(int, int) = Max; Int (*pmax)(int a, int bprintf("Input two numbers:");
    scanf("%d %d", &x, &y); maxval = (*pmax)(x, y); // Call the function and assign the pointerprintf("Max value: %d\n", maxval);

    return0; } // maxval calls the function. Pmax is a function pointer, preceded by * to indicate a call to the function it points to. Note that () takes precedence over * and the first parenthesis cannot be omitted.Copy the code

Pointer to a two-dimensional array:

A two-dimensional array is conceptually two-dimensional, with rows and columns, but in memory all array elements are arranged consecutively, with no “gaps” between them. Take the following two-dimensional array A as an example:

int a[3][4] = { {0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11} }; A is like a matrix: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11. However, in memory, the distribution of A is one-dimensional linear, and the whole array occupies a contiguous memory: [0] [1] [2] [3] [4] [6] [7] [8] [9] [10] [11]Copy the code

The two-dimensional array in C language is arranged in line, that is, a[0] line is stored first, then A [1] line is stored, and finally A [2] line is stored. The four elements in each row are also placed in sequence. Array A is an int. Each element occupies 4 bytes. The total size of the array is 48 bytes.

C language decomposes a two-dimensional array into multiple one-dimensional arrays to process. For array A, it can be decomposed into three one-dimensional arrays, namely A [0], a[1], and a[2]. Each one dimensional array and includes four elements, such as a [0] contains ` a [0] [0], a [0] [1], a [0] [2], a [0] [3].

To better understand the relationship between Pointers and two-dimensional arrays, let’s first define a pointer variable p to a:

int (*p)[4] = a; // The * in parentheses indicates that p is a pointer to an array of type int [4], which is the type of each of the one-dimensional arrays a contains.Copy the code

Int *p[4] int *(p[4]); p is an array of Pointers, not a two-dimensional array pointer.

When adding (subtracting) a pointer, its step forward (backward) depends on the data type to which it points. P points to int [4], so p+1 moves forward by 4×4 = 16 bytes, and p-1 moves back by 16 bytes, which is exactly the length of each one-dimensional array contained in array A. That is, p+1 makes the pointer point to the next row of the two-dimensional array, and p-1 makes the pointer point to the top row of the array.

As defined above, let’s look at the code:

#include <stdio.h>
int main(void){

    int a[3][4] = { {0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11} };
    int (*p)[4] = a;

    printf ( "%d\n", sizeof(*(p+1)) ); // Here the output is 16return 0;
}Copy the code

*(p+1)+1 represents the address of the first element in line 1: *(p+1), when used alone, represents the first row of data, which is converted to the address of the 0th element of the first row. Since the whole row has no real meaning, the compiler converts this to a pointer to the 0th element of the row. Like the name of a one-dimensional array, which represents the entire array when defined or when used with sizeof and &, it is converted to a pointer to the 0th element of the array when it appears in an expression.

  • *(*(p+1)+1) represents the value of the first element in line 1. Obviously, adding an * indicates fetching data from the address: **

Rule:  a+i == p+i a[i] == p[i] == *(a+i) == *(p+i) a[i][j] == p[i][j] == *(a[i]+j) == *(p[i]+j) == *(*(a+i)+j) == *(*(p+i)+j)#include<stdio.h>Int main (void) {int a [3] [4] = {{1, 2, 3, 4}, {5,6,7,8}, {9,10,11,12}}; int i, j; int(*p)[4] = a; // define a pointer to a two-dimensional array pfor (i = 0; i < 3; i++) {
		for (j = 0; j < 4; j++) {

			printf("%d ", *(*(p+i)+j)); //*(p+ I) : 1printf("\n"); //*(*(p+ I)+j)return0; } /* 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12Copy the code

Pointer arrays and Pointers to two-dimensional arrays are very similar in definition, but the placement of parentheses can mean very different things:

int *(p1[5]); Int *p1[5]; int (*p2)[5]; // A pointer to a two-dimensional array without parenthesesCopy the code

A pointer array is essentially different from a two-dimensional array pointer: a pointer array is an array, but each element holds a pointer. P1, for example, takes up 4×5 = 20 bytes of memory in a 32-bit environment. A pointer to a two-dimensional array is a pointer to a two-dimensional array, such as p2 above, which takes up 4 bytes of memory.

Multidimensional arrays are no different from two-dimensional arrays, but they are much more complex. Not commonly used.

Conclusion: in the process of running programs need is the address of data and instructions, variable, function name, name string and array name is the same in essence, they are all address mnemonic: in the process of writing code, we think that the variable name represents the data itself, and the function name, string and an array of said is the address of the first block of code or data block; When the program is compiled and linked, these names disappear, replaced by their corresponding addresses. A pointer is a variable that holds an address.

Common Pointers:

Set the righteous Containing righteousness
int *p; P can point to data of type int or to an array like int arr[n].
int **p; P is a second-level pointer to int *.
int *p[n]; P is an array of Pointers. Int *(p[n]); int *(p[n]);
int (*p)[n]; P is a pointer to a two-dimensional array.
int *p(); P is a function whose return type is int *.
int (*p)(); P is a function pointer to a function whose prototype is int func().

1. Pointer variables can perform four operations. Pointer variables do not simply add or subtract an integer, but depend on the type and address to which the pointer points.

Int *p = 1000; int *p = 1000; int *p = 1000; Is meaningless and generally causes the program to crash.

A pointer variable must be initialized before it is used, otherwise it cannot be determined where the pointer points to. If the memory it points to is not allowed to use, the program will crash. For a pointer that is not currently pointed to, assign NULL to make it NULL.

4. Arrays are also typed. Array names are meant to represent a group of data of the same type. When defining an array, or when used with sizeof and &, the array name represents the entire array, and the array name in the expression is converted to a pointer to the array.

Pointer usage is temporarily these, C pointer method these are the entry, the back continue to add..