当前位置:网站首页>Advanced C - Section 2 - pointers

Advanced C - Section 2 - pointers

2022-06-13 04:51:00 Stretch the curtain with the wind

Catalog

1. Character pointer

1.1. Character pointer

1.2. practice

2. Pointer array

2.1. Pointer array

2.2. Example

3. Array pointer

3.1. Definition of array pointer

3.2.& Array name and array name

3.3. The use of array pointers

3.4. A few code expressions mean

4. Array parameters , Pointer parameter

4.1. One dimensional array parameters

4.2. Two dimensional array parameters

4.3. First level pointer parameter transfer

4.3.1. First level pointer parameter transfer example

4.3.2. When the parameter part of a function is a first-order pointer , What parameters can a function take

4.4. The secondary pointer transmits parameters

4.4.1. Two level pointer parameter transfer example

4.4.2. When the parameter part of the function is a second-order pointer , What parameters can a function take

5. A function pointer

5.1. A function pointer

5.2. Two interesting codes

6. Function pointer array (※)

7. A pointer to an array of function pointers

8. Callback function (※)

9. Pointer and array written test question analysis

10. Pointer written test questions


1. Character pointer

1.1. Character pointer

int main()
{
    //1
    char ch='w';
    char* p=&ch;

    //2
    char* p="abcdef";
    *p='w';   // The statement is incorrect 

    //3
    const char* p="abcdef";

    return 0;
}

notes :

1. Code 1 Is to create variables ch,ch There are characters in the variable space 'w'; Define pointer variables to store variables ch The address of , Make pointer variable p Can point to variables ch Space

2. Code 2 The sentence of 1 Is the string "abcdef" A read-only data area stored in memory ( The data in the read-only data area can only be read ), Then the address of this string ( Initial address ) Put it in the pointer variable p in .

Code 2 The sentence of 2 It can't be realized , because "abcdef" There is a read-only data area , Cannot make changes ( Forced operation , The program will get stuck )

3. Code 3 It's code 2 sentence 1 Standard form of . Because the code 2 Data in a read-only data area cannot be changed , That is, you can't use pointer variables p To dereference , So use... In the front const Decorating code is more rigorous .( Some compilers do not add const There will be warnings )

1.2. practice

Exercise one :

#include<stdio.h>
int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abcdef";

	const char* str1 = "abcdef";
	const char* str2 = "abcdef";

	if (arr1 == arr2)
		printf("arr1==arr2\n");
	else
		printf("arr1!=arr2\n");

	if (str1 == str2)
		printf("str1==str2\n");
	else
		printf("str1!=str2\n");

	return 0;
}

Running results :

notes :

1.arr1 and arr2 Are two different arrays , The array name represents the address of the first element of the array , therefore arr1 It's not equal to arr2

2. Read only data area , Only one copy of the same data is saved , therefore , Code above str1 and str2 Both point to the string in the read-only data area "abcdef" The address of ( The first address )

Exercise 2 :

typedef int* pint;

#define PINT int*

int main()
{

    //1  
    int a,b;

    //2
    int * pa,pb;

    //3
    int * pa, * pb;

    //4
    pint pa,pb;

    //5
    PINT pa,pb;

    return 0;
}

notes :

1. Code 1 in : Variable a and b All are int type

2. Code 2 in : Variable pa yes int* type , It's a pointer variable ; Variable pb yes int type

3. Code 3 in : Variable pa and pb All are int* type , It's a pointer variable

4. Code 4 in : Variable pa and pb All are int* type , It's a pointer variable

5. Code 5 in : When the code runs, it will PINT Switch to int*, So the results and the code 2 identical .

    Variable pa yes int* type , It's a pointer variable ; Variable pb yes int type


2. Pointer array

2.1. Pointer array

Pointer array is an array of pointers
int* arr1[10];            // Class A An array of integer pointers      
int*int*int*int*int*int*int*int*int*int*
char *arr2[4];          // An array of first-order character pointers
char*char*char*char*
char **arr3[5];        // An array of secondary character pointers
char**char**char**char**char**

2.2. Example

example 1:

#include<stdio.h>

int main()
{
	char* arr[] = { "abcdef", "qwer", "zhangsan" };
	int i = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);

	for (i = 0; i < sz; i++)
	{
		printf("%s\n", arr[i]);
	}
	return 0;
}

Running results :

notes :

The array is stored in memory as shown in the following figure  :

example 2:
#include<stdio.h>

int main()
{
	int arr1[] = { 1,2,3,4,5 };
	int arr2[] = { 2,3,4,5,6 };
	int arr3[] = { 3,4,5,6,7 };

	int* arr[] = {arr1, arr2, arr3};

	int i = 0;
	for (i = 0; i < 3; i++)
	{
		int j = 0;
		for (j = 0; j < 5; j++)
		{
			printf("%d ", arr[i][j]);//*(*(arr+i)+j)
		}
		printf("\n");
	}

	return 0;
}

Running results :

notes : 

1. The array is stored in memory as shown in the following figure  :

2. In the code :arr[ i ][ j ]) and *(*(arr+i)+j) It's the same
3. Here we can see that the variable name of the pointer array is equivalent to a second level pointer

3. Array pointer

3.1. Definition of array pointer

Array pointers are pointers
Shaping the pointer : int * pint;        A pointer that can point to shaped data .
Floating point pointer : float * pf;    A pointer that can point to floating-point data .
The array pointer should be : A pointer to an array
int *p1[10];
int (*p2)[10];
//p1, p2 What are the differences ?
explain :
int *p1[10];
p1 The first and [ ] combination , explain p1 Is an array , There is *, Description is a pointer array
int (*p)[10];
p The first and * combination , explain p Is a pointer variable , Then point to a size of 10 An array of integers . therefore p It's a pointer , Point to an array , It's called array pointer .
Pay attention here :[ ] Priority is higher than * The no. , So we have to add () To guarantee p The first and * combination .

3.2.& Array name and array name

Code :

int main()
{
	int arr[10] = { 0 };
	printf("%p\n", arr);
	printf("%p\n", arr+1);

	printf("%p\n", &(arr[0]));
	printf("%p\n", &(arr[0])+1);

	printf("%p\n", &arr);
	printf("%p\n", &arr+1);


	return 0;
}

Running results :

  notes :

1.arr and &arr[0] Are the address of the first element of the array ,&arr Is the address of the array , Their values are the same , But the types are different

2. Integer variable address , Save up , Should exist in an integer pointer

    Character variable address , Save up , Should exist in a character pointer

    Address of array , Save up , It should also exist in the array pointer , as follows :

int (*p)[10]=&arr;

int [10] It's an array arr The type of ,* The representation is a pointer variable ,p Is a variable name. . Give pointer variables p Put an array in it arr The address of .

3.int* arr[6], To save the address of the pointer array in the array pointer , The array pointer definition should be int*(*p)[6]=&arr

3.3. The use of array pointers

Code 1(1):

Code 1(2):

 

Code 1 Of (1) and (2) The running results are the same , as follows :

notes :

1. Dereference array pointer , It is equivalent to getting the address of the first element of the array , That is, the array name (*p and arr It's the same ).

2. This usage of this example is very awkward , Don't use , It is only helpful to understand . Pointer arrays are generally used in two-dimensional arrays , Like the following code 2 Shown .

Code 2(1):

  Code 2(2):

notes :

1. The array name of a two-dimensional array represents the address of the first element of the array , The first element of the two-dimensional array is the first row of the two-dimensional array . in other words , The array name of the two-dimensional array is the address of the first row of the two-dimensional array . The type of the first line of the two-dimensional array in the above code is int [5], So the formal parameter is int (*p)[5] To receive

2. Because pointer variables p It's the first line , So here it is p+i, Is to point to a two-dimensional array i That's ok .*p Equivalent to the array name in the first row ( Array name is the address of the first element of the array , That is, the address of the first element in the first line ),*(p+i) It's equivalent to i Row array name ( That is the first. i The address of the first element of the line ).*(p+i)+j That is the first. i Xing di j Addresses of elements .*(*(p+i)+j) That is the first. i Xing di j Elements .

3. Similar to a one-dimensional array , Inside this *(p+i) amount to p[ i ],*(*(p+i)+j) amount to p[ i ][ j ]

3.4. A few code expressions mean

int arr[5];
int *parr1[10];
int (*parr2)[10];
int (*parr3[10])[5];

notes :

1.int arr[5];

arr It's an array of integers , Yes 5 Elements , Each element is int type


2.int *parr1[10];

parr1 Is an array , Array has 10 Elements , The type of each element is int*, therefore parr1 It's an array of pointers


3.int (*parr2)[10];

parr2 and * combination , explain parr2 It's a pointer , The pointer points to an array , An array is 10 Elements , Each element is int Type of .parr2 It's an array pointer .


4.int (*parr3[10])[5];

parr3 and [ ] combination , explain parr3 Is an array , An array is 10 Elements , Each element of an array is an array pointer , The type is int(*) [5], The array pointed to by this type of pointer is 5 individual int Element of type .parr3 Is a pointer array whose element is an array pointer .


4. Array parameters , Pointer parameter

When writing code, it is inevitable to 【 Array 】 perhaps 【 The pointer 】 Pass to function , How to design the parameters of a function

4.1. One dimensional array parameters

#include <stdio.h>
void test(int arr[])  //ok
{}

void test(int arr[10])  //ok
{}

void test(int *arr)  //ok
{}

void test2(int *arr[20])  //ok
{}

void test2(int **arr)  //ok
{}


int main()
{
 int arr[10] = {0};
 int *arr2[20] = {0};
 test(arr);
 test2(arr2);
}

notes :

1. Array parameters , Formal parameters can be written in the form of arrays .( Write in array form , The array size can be written or not , It doesn't matter if you write it wrong , Because the array will not be created at all here )

2. Array parameters , The argument passes the array name , The array name is equivalent to the address of the first element , So formal parameters can be written in the form of pointers

3. If each element in the array passed by the argument is int type , Then if the formal parameter is received with a pointer , Should use the int* Receive its address .

    If each element in the array passed by the argument is int* type , Then if the formal parameter is received with a pointer , Should use the int** Receive its address .

4.2. Two dimensional array parameters

void test(int arr[3][5])  //ok
{}

void test(int arr[][])  //no
{}

void test(int arr[][5])  //ok
{}

void test(int *arr)  //no
{}

void test(int* arr[5])  //no
{}

void test(int (*arr)[5])  //ok
{}

void test(int **arr)  //no
{}


int main()
{
 int arr[3][5] = {0};
 test(arr);
}

notes :

1. Array parameters , Formal parameters can be written in the form of arrays .( Write in array form , Rows in the array size can be omitted , Columns cannot be omitted , Because if the column is omitted, it is not a two-dimensional array , A two-dimensional array , I don't know how many lines there are , But you have to know how many elements in a row

2. Two dimensional array parameters , The argument passes the array name , The array name of a two-dimensional array is equivalent to the address of the first element , The address of the first element here is the address of the first row of the two-dimensional array .

3. The above code , The type of the first row of a two-dimensional array is int [5], If a parameter is received with a pointer , Should use the int (*) [5] To receive the address .

4.3. First level pointer parameter transfer

4.3.1. First level pointer parameter transfer example

#include <stdio.h>

void print(int *p, int sz) 
{
 int i = 0;
 for(i=0; i<sz; i++)
 {
 printf("%d\n", *(p+i));
 }
}

int main()
{
 int arr[10] = {1,2,3,4,5,6,7,8,9};
 int *p = arr;
 int sz = sizeof(arr)/sizeof(arr[0]);
 // First level pointer p, Pass to function 
 print(p, sz);
 return 0; 
}

4.3.2. When the parameter part of a function is a first-order pointer , What parameters can a function take

void test(int* p)
{}

int main()
{
	int a = 10;
	int* ptr = &a;
	int arr[10] = {0};

	test(&a);
	test(ptr);
	test(arr);

	return 0;
}

notes :

1. You can pass the address of a variable , Can pass a pointer variable , You can pass the array name

2. When using other people's function code in the future , We can know how to pass parameters

4.4. The secondary pointer transmits parameters

4.4.1. Two level pointer parameter transfer example

#include <stdio.h>

void test(int** ptr) 
{
 printf("num = %d\n", **ptr); 
}

int main()
{
 int n = 10;
 int*p = &n;
 int **pp = &p;

 test(pp);
 test(&p);

 return 0; 
}

4.4.2. When the parameter part of the function is a second-order pointer , What parameters can a function take

void test(char** p)
{}

int main()
{
	char ch = 'w';
	char* p = &ch;
	char** pp = &p;
	char* arr[5];

	test(&p);
	test(pp);
	test(arr);

	return 0;
}

notes :

1. You can pass the address of a first level pointer variable , Can pass two pointer variables , The array name of the first level pointer array can be passed

2. When using other people's function code in the future , We can know how to pass parameters


5. A function pointer

5.1. A function pointer

Code 1:

int Add(int x, int y)
{
	return x + y;
}

int main()
{
	printf("%p\n", &Add);
	printf("%p\n", Add);
	
	return 0;
}

notes : Unlike arrays ,& Function name and function name get the address of the function , Functions have no concept of the first element .

Code 2:

int Add(int x, int y)
{
	return x + y;
}

void test(char* str)
{}

int main()
{

	int arr[5];
	int (*pa)[5] = &arr;  //pa It's an array pointer 

	int (* pf)(int, int) = &Add;  //pf It's a function pointer 
	int (* pf)(int, int) = Add;

	void (*pt)(char*) = test;

	return 0;
}

notes :

1. Functions also have data types , Like the code above Add The data type of the function is int  (int,int),test Similarity of functions .

2. Function pointer variables are defined in the form of :int (*pf) (int,int),pf Is the function pointer variable name ,pf And * The combination shows that it is a pointer , The pointer points to a data type of int  (int,int) Function address of .test Similarity of functions .

3.Add Is the function name , It is also the address of the function , and pf What you receive is the function address (&Add or Add), therefore pf The essence of Add identical ( And int* p=arr,p and arr Is essentially the same )

Code 3:

int Add(int x, int y)
{
	return x + y;
}


int main()
{

	int (* pf)(int, int) = Add;

	int sum = (*pf)(2,3);
	int sum = pf(2, 3);
	int sum = Add(2, 3);
	printf("%d\n", sum);

	return 0;
}

notes :

1. Dereference function pointer variables (*pf) You get this function , That is, the function name (Add)

2. because pf It is essentially the same as the function name Add It's the same , Therefore, there is no need to dereference , direct pf(2, 3) Call function .

5.2. Two interesting codes

Code 1:

(*(void (*)())0)();

notes :

1.void (*)() Is a function pointer type , Put parentheses on it ( void (*)() ) Represents cast ;

( void (*)() )0 Is to put 0 Cast to function pointer type , Address 0 The local data type is cast to void (*)(), Equivalent to address 0 There is a type of void (*)() Function of ;

*( void (*)() )0, Dereference is equivalent to getting the function name , This function can then be called ;

( *( void (*)() )0 )() This is a function call , call 0 The function at the address . It is called because the function pointer type has no parameters , Therefore, there is no reference in the brackets .

2. This is a special code , Users cannot directly access 0 Address of the

Code 2:

void ( *signal( int , void(*)(int) ) )(int);

notes :

1. Parentheses take precedence over *,signal First, it should be combined with the following parentheses , therefore signal Is a function name .

signal (int , void(*)(int) ),signal No parameter is passed in the following brackets , This is a function declaration , This code signal Is the function name , The first argument to the function is an integer int type , The second parameter is the function pointer type ;

void ( *signal( int , void(*)(int) ) )(int) After removing the function name and function parameters, the rest should be the return type

void ( * )(int) Is the return type of this function , This type is a function pointer

 2. This code can be simplified

We want to be right void(*)(int) Start a new name pfun_t, here pfun_t Is the name of a new function pointer type . But we can't use typedf void(*)(int) pfun_t This form defines , And should typedf void(* pfun_t)(int) That's the definition . Note that there pfun_t Not the name of a function pointer variable , It is the name of the function pointer type , as follows :

void (*p) (int)    //p Is the name of the function pointer variable 
typedef void(*pf_t)(int)  //pf_t Is the type name 

here , You can use it pfun_t representative

void(*)(int) The type of this pointer . The simplified code is as follows :

typedf void(* pfun_t)(int);

pfun_t signal(int,pfun_t)

3. The code is used in the following way :


6. Function pointer array

int* arr[4]      Array of integer pointers , Each element is an integer

char* arr[5]  Character pointer array , Each element is a character type

int (*pfArr[4])(int,int) Function pointer array , Each element is a function pointer

Function pointer array is an array of function pointers , Each element is a function pointer type

Code 1:(※)

int Add(int x, int y)
{
	return x + y;
}
int Sub(int x, int y)
{
	return x - y;
}
int Mul(int x, int y)
{
	return x * y;
}
int Div(int x, int y)
{
	return x / y;
}

int main()
{


	int (*pfArr[4])(int, int) = {Add, Sub, Mul, Div};// Function pointer array 
	int i = 0;
	for (i = 0; i < 4; i++)
	{
		
		int ret = pfArr[i](8, 4);

		printf("%d\n", ret);
	}
	return 0;
}

Running results :

  notes :

In the above code int ret = pfArr[i](8, 4) And int ret = (*pfArr[i])(8, 4) It's essentially the same , It can be used

int ret = (*pfArr[i])(8, 4) Replace .

Code 2(1):(※)

int Add(int x, int y)
{
	return x + y;
}
int Sub(int x, int y)
{
	return x - y;
}
int Mul(int x, int y)
{
	return x * y;
}
int Div(int x, int y)
{
	return x / y;
}


void menu()
{
	printf("**********************************\n");
	printf("*****  1. add     2. sub     *****\n");
	printf("*****  3. mul     4. div     *****\n");
	printf("*****  0. exit               *****\n");
	printf("**********************************\n");
}

int main()
{
	int input = 0;
	int x = 0;
	int y = 0;
	int ret = 0;
	do
	{
		menu();
		printf(" Please select :>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf(" Input 2 Operands :>");
			scanf("%d %d", &x, &y);
			ret = Add(x, y);
			printf("ret = %d\n", ret);
			break;
		case 2:
			printf(" Input 2 Operands :>");
			scanf("%d %d", &x, &y);
			ret = Sub(x, y);
			printf("ret = %d\n", ret);
			break;
		case 3:
			printf(" Input 2 Operands :>");
			scanf("%d %d", &x, &y);
			ret = Mul(x, y);
			printf("ret = %d\n", ret);
			break;
		case 4:
			printf(" Input 2 Operands :>");
			scanf("%d %d", &x, &y);
			ret = Div(x, y);
			printf("ret = %d\n", ret);
			break;
		case 0:
			printf(" Exit calculator \n");
			break;
		default:
			printf(" Wrong choice \n");
			break;
		}
	} while (input);

	return 0;
}

Code 2(2):( Improved version )(※)

int Add(int x, int y)
{
	return x + y;
}
int Sub(int x, int y)
{
	return x - y;
}
int Mul(int x, int y)
{
	return x * y;
}
int Div(int x, int y)
{
	return x / y;
}


void menu()
{
	printf("**********************************\n");
	printf("*****  1. add     2. sub     *****\n");
	printf("*****  3. mul     4. div     *****\n");
	printf("*****  0. exit               *****\n");
	printf("**********************************\n");
}

int main()
{
	int input = 0;
	int x = 0;
	int y = 0;
	int ret = 0;

	int (*pfArr[5])(int, int) = { 0, Add, Sub, Mul, Div };//pfArr Is an array of function pointers , Also called transfer table 

	do
	{
		menu();
		printf(" Please select :>");
		scanf("%d", &input);
		if (input == 0)
		{
			printf(" Exit calculator \n");
			break;
		}
		else if (input >= 1 && input <= 4)
		{
			printf(" Input 2 Operands :>");
			scanf("%d %d", &x, &y);
			ret = pfArr[input](x, y);
			printf("ret = %d\n", ret);
		}
		else
		{
			printf(" Wrong choice \n");
		}
	} while (input);

	return 0;
}

notes :

1.pfArr Is an array of function pointers , Also called transfer table

2. The precondition for this improvement with function pointer array is that the number and type of parameters of each function in the function pointer array are the same .


7. A pointer to an array of function pointers

Code :

int Add(int x, int y)
{
	return x + y;
}

int main()
{

	int (*pa)(int, int) = Add;  // A function pointer 

	int (* pfA[4])(int, int);  // An array of function pointers 

	int (* (*ppfA)[4])(int, int) = &pfA;  //ppfA  It's a pointer , The pointer points to an array of function pointers 

	return 0;
}

notes :

1. Function pointer arrays are also typed , As shown in the above code ,int (*  [4])(int, int) Is the type of function pointer array . So if you create a pointer that holds an array of function pointers ,*ppfa Make the variable name , Add the function pointer array type outside .

2. Above code ppfA It's a pointer , The pointer points to an array of function pointers


8. Callback function

A callback function is a function called through a function pointer . If you put a pointer to a function ( Address ) Pass as argument to another function , When this pointer is used to call the function it points to , Let's say that the function pointed to by the function pointer is a callback function . The callback function is not called directly by the function's implementer , It's called by another party when a particular event or condition occurs , Used to respond to the event or condition .

example 1:( Improvements to calculator code )(※)

Code :

#include<stdio.h>

void menu()
{
	printf("**********************************\n");
	printf("*****  1. add     2. sub     *****\n");
	printf("*****  3. mul     4. div     *****\n");
	printf("*****  0. exit               *****\n");
	printf("**********************************\n");
}

int Add(int x, int y)
{
	return x + y;
}
int Sub(int x, int y)
{
	return x - y;
}
int Mul(int x, int y)
{
	return x * y;
}
int Div(int x, int y)
{
	return x / y;
}

void calc(int (*pf)(int, int))
{
	int x = 0;
	int y = 0;
	int ret = 0;
	printf(" Input 2 Operands :>");
	scanf("%d %d", &x, &y);
	ret = pf(x, y);
	printf("ret = %d\n", ret);
}

int main()
{
	int input = 0;

	do
	{
		menu();
		printf(" Please select :>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			calc(Add);
			break;
		case 2:
			calc(Sub);
			break;
		case 3:
			calc(Mul);
			break;
		case 4:
			calc(Div);
			break;
		case 0:
			printf(" Exit calculator \n");
			break;
		default:
			printf(" Wrong choice \n");
			break;
		}
	} while (input);

	return 0;
}

example 2:( simulation qsort Library function )

1.qsort Function introduction :

Simplify the above parameters as shown in the following figure

 

  notes :

1. The first parameter base: The beginning of the target array , That is, the starting position of the sorted data , Pass to base.

2. The second parameter num: Size of array , Number of array elements

3. The third parameter width: The size of each element in the array ( Number of bytes taken ).

4. Fourth parameter compare: Comparison function , The return value of the comparison function satisfies the following rules

 5.void* Is a pointer without a specific type .

    void* The pointer variable of can store any type of address .

    void* The pointer of cannot be dereferenced directly , Nor can it be done directly +/- Positive operation .

2. Use qsort Examples of functions (※)

Code 1:

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

void print_arr(int arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
}


int cmp_int(const void* e1, const void* e2)
{
	return *(int*)e1 - *(int*)e2;
}


int main()
{
	int arr[] = { 1,4,2,6,5,3,7,9,0,8 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(arr[0]), cmp_int);

	print_arr(arr, sz);

	return 0;
}

Running results :

  notes :

1.cmp_int The parameter passed in by the function itself is void* Pointer to type , Therefore, if you want to dereference it in the function body , It needs to be cast to the corresponding pointer variable type in advance

2. In the code ,*(int*)e1 - *(int*)e2 The code is a simplified version of the following code

3. To change ascending order into descending order , take *(int*)e1 - *(int*)e2 Change to *(int*)e2 - *(int*)e1 that will do .

4. quote qsort function , need stdlib.h The header file

Code 2(1):( Structure score comparison )

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


struct Stu
{
	char name[20];
	int age;
	float score;
};

int cmp_stu_by_socre(const void* e1, const void* e2)
{
	if (((struct Stu*)e1)->score > ((struct Stu*)e2)->score)
	{
		return 1;
	}
	else if (((struct Stu*)e1)->score < ((struct Stu*)e2)->score)
	{
		return -1;
	}
	else
	{
		return 0;
	}
}

void print_stu(struct Stu arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%s %d %f\n", arr[i].name, arr[i].age, arr[i].score);
	}
	printf("\n");
}

int main()
{
	struct Stu arr[] = { {"zhangsan",20,87.5f},{"lisi",22,99.0f},{"wangwu", 10, 68.5f} };
	int sz = sizeof(arr) / sizeof(arr[0]);

	qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_socre);
	print_stu(arr, sz);
	return 0;
}

Running results :

  notes :

1. In this comparison, two structural variables are compared , The parameter passes two structure pointers , Therefore, dereference needs to be cast to structure pointer type , In the process of dereferencing

2. In the above code , The comparison code in the function body cannot be reduced to the form of subtraction ( such as 0.9-0.8=0.1, The previous return type is an integer int,0.1 Back to you 0, The result error )

Code 2(2):( Age comparison of structures )

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


struct Stu
{
	char name[20];
	int age;
	float score;
};

int cmp_stu_by_age(const void* e1, const void* e2)
{
	return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
}

void print_stu(struct Stu arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%s %d %f\n", arr[i].name, arr[i].age, arr[i].score);
	}
	printf("\n");
}

int main()
{
	struct Stu arr[] = { {"zhangsan",20,87.5f},{"lisi",22,99.0f},{"wangwu", 10, 68.5f} };
	int sz = sizeof(arr) / sizeof(arr[0]);

	qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_age);

	print_stu(arr, sz);
	return 0;
}

Running results :

Code 2(3):( Structure name comparison )

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


struct Stu
{
	char name[20];
	int age;
	float score;
};

int cmp_stu_by_name(const void* e1, const void* e2)
{
	return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);
}

void print_stu(struct Stu arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%s %d %f\n", arr[i].name, arr[i].age, arr[i].score);
	}
	printf("\n");
}

int main()
{
	struct Stu arr[] = { {"zhangsan",20,87.5f},{"lisi",22,99.0f},{"wangwu", 10, 68.5f} };
	int sz = sizeof(arr) / sizeof(arr[0]);

	qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_name);

	print_stu(arr, sz);
	return 0;
}

Running results :

  notes :

1.strcmp The compare() function compares the contents of a string ( character-based ASCII Code value for comparison )( Start with the first character , If the same, compare the second character )

2.strcmp need string.h The header file

3. Simulation Implementation qsort Library function

Code 1( Implementation of integer array sorting ):

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

void Swap(char* buf1, char* buf2, int width)
{
	int i = 0;
	for (i = 0; i < width; i++)
	{
		char tmp = *buf1;
		*buf1 = *buf2;
		*buf2 = tmp;
		buf1++;
		buf2++;
	}
}

void bubble_sort(void* base, int sz, int width, int(*cmp)(const void* e1, const void* e2))
{
	int i = 0;
	for (i = 0; i < sz - 1; i++)
	{
		int j = 0;
		for (j = 0; j < sz - 1 - i; j++)
		{
			//if (arr[j] > arr[j + 1])
			if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)
			{
				// The exchange of two elements 
				Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);
			}
		}
	}
}

int cmp_int(const void* e1, const void* e2)
{
	return *(int*)e1 - *(int*)e2;
}

void print_arr(int arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
}

void test1()
{
	int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz, sizeof(arr[0]), cmp_int);
	print_arr(arr, sz);
}

int main()
{
	test1();
	return 0;
}

Code 2( Realize the sorting of structure scores ):

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

void Swap(char* buf1, char* buf2, int width)
{
	int i = 0;
	for (i = 0; i < width; i++)
	{
		char tmp = *buf1;
		*buf1 = *buf2;
		*buf2 = tmp;
		buf1++;
		buf2++;
	}
}

void bubble_sort(void* base, int sz, int width, int(*cmp)(const void* e1, const void* e2))
{
	int i = 0;
	for (i = 0; i < sz - 1; i++)
	{
		int j = 0;
		for (j = 0; j < sz - 1 - i; j++)
		{
			//if (arr[j] > arr[j + 1])
			if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)
			{
				// The exchange of two elements 
				Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);
			}
		}
	}
}

struct Stu
{
	char name[20];
	int age;
	float score;
};

int cmp_stu_by_socre(const void* e1, const void* e2)
{
	if (((struct Stu*)e1)->score > ((struct Stu*)e2)->score)
	{
		return 1;
	}
	else if (((struct Stu*)e1)->score < ((struct Stu*)e2)->score)
	{
		return -1;
	}
	else
	{
		return 0;
	}
}

void print_stu(struct Stu arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%s %d %f\n", arr[i].name, arr[i].age, arr[i].score);
	}
	printf("\n");
}

void test2()
{
	struct Stu arr[] = { {"zhangsan",20,87.5f},{"lisi",22,99.0f},{"wangwu", 10, 68.5f} };

	int sz = sizeof(arr) / sizeof(arr[0]);

	bubble_sort(arr, sz, sizeof(arr[0]), cmp_stu_by_socre);

	print_stu(arr, sz);
}

int main()
{
	test2();
	return 0;
}

Code 3( Realize the sorting of structure age ):

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

void Swap(char* buf1, char* buf2, int width)
{
	int i = 0;
	for (i = 0; i < width; i++)
	{
		char tmp = *buf1;
		*buf1 = *buf2;
		*buf2 = tmp;
		buf1++;
		buf2++;
	}
}

void bubble_sort(void* base, int sz, int width, int(*cmp)(const void* e1, const void* e2))
{
	int i = 0;
	for (i = 0; i < sz - 1; i++)
	{
		int j = 0;
		for (j = 0; j < sz - 1 - i; j++)
		{
			//if (arr[j] > arr[j + 1])
			if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)
			{
				// The exchange of two elements 
				Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);
			}
		}
	}
}

struct Stu
{
	char name[20];
	int age;
	float score;
};

int cmp_stu_by_age(const void* e1, const void* e2)
{
	return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
}

void print_stu(struct Stu arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%s %d %f\n", arr[i].name, arr[i].age, arr[i].score);
	}
	printf("\n");
}

void test3()
{
	struct Stu arr[] = { {"zhangsan",20,87.5f},{"lisi",22,99.0f},{"wangwu", 10, 68.5f} };

	int sz = sizeof(arr) / sizeof(arr[0]);

	bubble_sort(arr, sz, sizeof(arr[0]), cmp_stu_by_age);

	print_stu(arr, sz);
}

int main()
{
	test3();
	return 0;
}

Code 4( Implement the sorting of structure names ):

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

void Swap(char* buf1, char* buf2, int width)
{
	int i = 0;
	for (i = 0; i < width; i++)
	{
		char tmp = *buf1;
		*buf1 = *buf2;
		*buf2 = tmp;
		buf1++;
		buf2++;
	}
}

void bubble_sort(void* base, int sz, int width, int(*cmp)(const void* e1, const void* e2))
{
	int i = 0;
	for (i = 0; i < sz - 1; i++)
	{
		int j = 0;
		for (j = 0; j < sz - 1 - i; j++)
		{
			//if (arr[j] > arr[j + 1])
			if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)
			{
				// The exchange of two elements 
				Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);
			}
		}
	}
}

struct Stu
{
	char name[20];
	int age;
	float score;
};

int cmp_stu_by_name(const void* e1, const void* e2)
{
	return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);
}

void print_stu(struct Stu arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%s %d %f\n", arr[i].name, arr[i].age, arr[i].score);
	}
	printf("\n");
}

void test4()
{
	struct Stu arr[] = { {"zhangsan",20,87.5f},{"lisi",22,99.0f},{"wangwu", 10, 68.5f} };

	int sz = sizeof(arr) / sizeof(arr[0]);

	bubble_sort(arr, sz, sizeof(arr[0]), cmp_stu_by_name);

	print_stu(arr, sz);
}

int main()
{
	test4();
	return 0;
}

notes :

1. because base yes void* type , Therefore, you cannot directly dereference , Only cast types to other pointer types can dereference , But the sort type of this function is not certain , There is no way to uniquely identify a pointer type . We use char* Pointer type dereference , And use width Parameters can accurately access each element .

2.swap Function , Because I don't know what type it is , We use char* Solved , Also used when transferring parameters char*, If the variable data to be exchanged is multiple bytes , We can exchange bytes one by one


9. Pointer and array written test question analysis

Code 1:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>

int main() 
{

	int a[] = { 1,2,3,4 };
	printf("%d\n", sizeof(a));
	printf("%d\n", sizeof(a + 0));
	printf("%d\n", sizeof(*a));
	printf("%d\n", sizeof(a + 1));
	printf("%d\n", sizeof(a[1]));
	printf("%d\n", sizeof(&a));
	printf("%d\n", sizeof(*&a));
	printf("%d\n", sizeof(&a + 1));
	printf("%d\n", sizeof(&a[0]));
	printf("%d\n", sizeof(&a[0] + 1));

	return 0;
}

x86 Compilation result :

 x64 Compilation result :

  notes :

1. Array name is the address of the first element of the array , There are two exceptions :

(1)sizeof( Array name ), The array name here represents the whole array , It calculates the size of the entire array , Unit is byte .

(2)& Array name , The array name here also represents the whole array , What we get is the address of the array .

In addition to the above two special cases , All array names are the address of the first element of the array

2.sizeof(a+0): This is not an array list sizeof Inside , Therefore, the array name here is the address of the first element of the array ,a+0 Or the address of the first element of the array , Yes, the address size is 4/8 byte

3.sizeof(*a): This is not an array list sizeof Inside , Therefore, the array name here is the address of the first element of the array ,*a Is a dereference to the address of the first element of the array , It's the first element , The first element is int Type account 4 Bytes

4.sizeof(a+1): This is not an array list sizeof Inside , Therefore, the array name here is the address of the first element of the array ,a+1 Is the address of the second element , Yes, the address size is 4/8 byte

5.sizeof(a[1]):a[1] Is the second element of the array , Size is 4 Bytes

6.sizeof(&a):&a Represents the address of the array , The address of the array is also the address , The address size is 4/8 byte .

7.sizeof(*&a):&a Represents the address of an array , The type is int (*) [4] .*&a It is equivalent to dereferencing the address of an array ( Dereference array pointer ), The result is the array name of the array ,sizeof( Array name ) Is the memory size occupied by the array , Size is 16 Bytes

8.sizeof(&a+1):&a What we get is an array a The address of , The address of the array is the address of the first element ,&a+1 Is to skip the entire array 16 Address after bytes , Yes, the address is 4/8 byte

9.sizeof(&a[0]):&a[0] Get the address of the first element of the array , Yes, the address is 4/8 byte

10.sizeof(&a[0]+1):&a[0] Get the address of the first element of the array ,&a[0]+1 Is the address of the second element , Yes, the address size is 4/8 byte

Code 2:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>

int main()
{
	char arr[] = { 'a','b','c','d','e','f' };

	printf("%d\n", sizeof(arr));
	printf("%d\n", sizeof(arr + 0));
	printf("%d\n", sizeof(*arr));
	printf("%d\n", sizeof(arr[1]));
	printf("%d\n", sizeof(&arr));
	printf("%d\n", sizeof(&arr + 1));
	printf("%d\n", sizeof(&arr[0] + 1));

	return 0;
}

x86 Compilation result :

  x64 Compilation result :

notes :

1.sizeof(arr):arr As an array, the list is placed alone in sizeof Inside , Calculate the size of the entire array , Occupy 6 Bytes .
2.sizeof(arr + 0): This is not an array list sizeof Inside , Therefore, the array name here is the address of the first element of the array ,arr+0 The address of the first element of the array , The address size is 4/8 byte
3.sizeof(*arr): This is not an array list sizeof Inside , Therefore, the array name here is the address of the first element of the array ,*arr Is the first element of an array , The first element is a character , Occupy 1 Bytes
4.sizeof(arr[1]):arr[1] Is the second element of the array , Is a character , Occupy 1 Bytes
5.sizeof(&arr):&arr What we get is the address of the array , The address of the array is also the address , The address is 4/8 Bytes
6.sizeof(&arr + 1):&arr What we get is the address of the array ,&arr+1 Skipped the entire array ,&arr+1 Or the address , The address is 4/8 Bytes
7.sizeof(&arr[0] + 1):&arr[0] Is the address of the first element ,&arr[0] + 1 Is the address of the second element , The address is 4/8 Bytes

Code 3:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include <string.h>


int main()
{
	char arr[] = { 'a','b','c','d','e','f' };

	printf("%d\n", strlen(arr));
	printf("%d\n", strlen(arr + 0));
    printf("%d\n", strlen(*arr));
    printf("%d\n", strlen(arr[1]));
	printf("%d\n", strlen(&arr));
	printf("%d\n", strlen(&arr + 1));
	printf("%d\n", strlen(&arr[0] + 1));

	return 0;
}

Compilation result :( The compilation result is not fixed ,*arr and arr[1] Because of mistakes , Run without compilation )

 

 

notes :

1.sizeof Just focus on the size of the occupied space , Unit is byte ;sizeof Don't pay attention to type ;sizeof It's the operator

   strlen Attention string \0 The location of , The calculation is \0 How many characters have appeared before ;strlen For strings only ;stelen        It's a library function

2.strlen(arr): here arr Is the address of the first element of the array , however arr There is no \0, When calculating, I don't know when to stop , The result is a random value 1

3.strlen(arr + 0): here arr Is the address of the first element of the array ,arr+0 Or the address of the first element of the array ,arr There is no \0, The result is a random value 1

4.strlen(*arr):strlen What you need is an address , Start at this address and look back for characters , until \0, Count the number of characters . but *arr Is the first element of the array , That is to say 'a', Now it's passed on to strlen is 'a' Of ASCII value 97,strlen The function takes 97 As the starting address , Statistics string , Memory access conflicts will occur , Here's the picture .(strlen The function also performs type checking on the received parameters , The type of check does not match , There will be indirect levels / Warnings of different types , Here's the picture )

5. strlen(arr[1]):arr[1] Is the second element of the array , That is to say 'b', Same as the previous error , Memory access conflict .

6.strlen(&arr):&arr What we get is the address of the array , At this point, the address of the starting position is taken , But the address type is array pointer type char (*) [6], Because the extracted address is the address of the first element , So the output is a random value 1, Because the address type is array pointer type , And strlen The parameter types are different , Indirect level will be reported / Warnings of different types

7.strlen(&arr + 1):&arr + 1 Skip an array , Get is arr The address of the byte following the array ,  The output is a random value 2( Random value 2= Random value 1-6), The address type is array pointer type , And strlen The parameter types are different , Indirect level will be reported / Warnings of different types

8.strlen(&arr[0] + 1):&arr[0] + 1 What you get is the address of the second element , The output is a random value 3( Random value 3= Random value 1-1)

Code 4:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include <string.h>

int main()
{
	char arr[] = "abcdef";

	printf("%d\n", sizeof(arr));
	printf("%d\n", sizeof(arr + 0));
	printf("%d\n", sizeof(*arr));
	printf("%d\n", sizeof(arr[1]));
	printf("%d\n", sizeof(&arr));
	printf("%d\n", sizeof(&arr + 1));
	printf("%d\n", sizeof(&arr[0] + 1));

	return 0;
}

x86 Compilation result :

 x64 Compilation result :

notes :

1.sizeof(arr):arr As an array, the list is placed alone in sizeof Inside , Calculate the size of the entire array , Occupy 7 Bytes

2.sizeof(arr + 0): This is not an array list sizeof Inside , Therefore, the array name here is the address of the first element of the array ,arr+0 Or the first element address , Yes, the address size is 4/8 byte

3.sizeof(*arr): This is not an array list sizeof Inside , Therefore, the array name here is the address of the first element of the array ,*arr Is the first element of the array , The element is a character , Occupy 1 Bytes

4.sizeof(arr[1]):arr[1] Is the second element of the array , Is a character , Occupy 1 Bytes

5.sizeof(&arr):&arr Fetch the address of the entire array , Yes, the address size is 4/8 byte

6.sizeof(&arr + 1):&arr+1 What you get is to skip this array , The address after the array , Yes, the address size is 4/8 byte

7.sizeof(&arr[0] + 1):&arr[0] + 1 Take the address of the second element , Yes, the address size is 4/8 byte

Code 5:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include <string.h>

int main()
{
	char arr[] = "abcdef";
	printf("%d\n", strlen(arr));
	printf("%d\n", strlen(arr + 0));
	printf("%d\n", strlen(*arr));
	printf("%d\n", strlen(arr[1]));
	printf("%d\n", strlen(&arr));
	printf("%d\n", strlen(&arr + 1));
	printf("%d\n", strlen(&arr[0] + 1));

	return 0;
}

Compilation result :( The compilation result of the penultimate value is not fixed ,*arr and arr[1] Because of mistakes , Run without compilation )

 

 

notes :

1.strlen(arr):arr Represents the address of the first element of the array , The length is 6

2.strlen(arr + 0):arr+0 Represents the address of the first element of the array , The length is 6

3.strlen(*arr):*arr Is the first element of the array 'a', It is equivalent to passing characters 'a' Of ASCII value 97, Memory access conflict , The system will report the indirect level / Warnings of different types

4.strlen(arr[1]):arr[1] Is the second element of the array 'b', It is equivalent to passing characters 'b' Of ASCII value 98, Memory access conflict , The system will report the indirect level / Warnings of different types

5.strlen(&arr):&arr It takes out the address of the entire array , The address of the entire array is the address of the first element , The length is 6; The address type is array pointer type , And strlen The parameter types are different , Indirect level will be reported / Warnings of different types

6.strlen(&arr + 1):&arr + 1 Skip the entire array , Point to the address after the array , Because I skipped \0, So it is a random value

7.strlen(&arr[0] + 1):&arr[0] + 1 For the address of the second element , The length is 5

Code 6:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include <string.h>

int main()
{
	char* p = "abcdef";

	printf("%d\n", sizeof(p)); 
	printf("%d\n", sizeof(p + 1));
	printf("%d\n", sizeof(*p));
	printf("%d\n", sizeof(p[0]));
	printf("%d\n", sizeof(&p));
	printf("%d\n", sizeof(&p + 1)); 
	printf("%d\n", sizeof(&p[0] + 1));

	return 0;
}

x86 Compilation result :

 x64 Compilation result :

  notes :

1.sizeof(p):p Is a pointer variable , Point to the first character in the string 'a' The address of ,sizeof(p) The calculation is the size of the pointer variable ,4/8 Bytes

2.sizeof(p + 1):p+1 Points to the second character of the string 'b' The address of ,4/8 Bytes

3.sizeof(*p):p yes char* Pointer to type , Dereference access 1 Bytes , That is, the first element of the string 'a',1 Bytes

4.sizeof(p[0]):p[0] Equivalent to *(p+0) Equivalent to *p, Same as the previous code ,1 Bytes

5.sizeof(&p):&p It's a pointer variable p The address of , The type is char**, Yes, the address is 4/8 Bytes

6.sizeof(&p + 1):&p It's a pointer variable p The address of , The type is char**,&p + 1 Skip the space occupied by an address, that is 4/8 Bytes , Point to the address following the address , Yes, the address is 4/8 Bytes

7.sizeof(&p[0] + 1):p[0] Equivalent to *p,*p Is the first element, the character 'a',&p[0] + 1 It's the second element 'b' The address of , Yes, the address is 4/8 Bytes

Code 7:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include <string.h>

int main()
{
	char* p = "abcdef";

	printf("%d\n", strlen(p));
	printf("%d\n", strlen(p + 1));
	printf("%d\n", strlen(*p));
	printf("%d\n", strlen(p[0]));
	printf("%d\n", strlen(&p));
	printf("%d\n", strlen(&p + 1));
	printf("%d\n", strlen(&p[0] + 1));

	return 0;
}

Compilation result :( Compilation results of the penultimate and third values are not fixed ,*p and p[0] Because of mistakes , Run without compilation )

  notes :

1.strlen(p):p Is a pointer variable , Point to the first character in the string 'a' The address of ,strlen(p) It's from 'a' Find the length of the string backward from the position of , The length is 6

2.strlen(p + 1):p+1 Get the second element 'b' The address of ,strlen(p+1) It's from 'b' Find the length of the string backward from the position of , The length is 5

3.strlen(*p):p Point to the first character in the string 'a' The address of ,*p Is the first element of the string 'a', Also is to 97 Pass to strlen function , Memory access conflict , The system will report the indirect level / Warnings of different types

4.strlen(p[0]):p[0] Equivalent to *(p+0) Equivalent to *p, Same code as above , Memory access conflict , The system will report the indirect level / Warnings of different types

5.strlen(&p):&p What is taken out is the pointer variable p The address of , Pass to strlen The function calculates the length to get a random value

6.strlen(&p + 1):&p+1 What is taken out is the pointer variable p Skip the four byte address later , Pass to strlen The function calculates the length to get a random value

7.strlen(&p[0] + 1):&p[0] + 1 The result is the second element of the string 'b' The address of ,strlen(&p[0] + 1) It's from 'b' Find the length of the string backward from the position of , The length is 5

Code 8:

int main()
{
	// Two dimensional array 
	int a[3][4] = { 0 };

	printf("%d\n", sizeof(a));
	printf("%d\n", sizeof(a[0][0]));
	printf("%d\n", sizeof(a[0]));
	printf("%d\n", sizeof(a[0] + 1));
	printf("%d\n", sizeof(*(a[0] + 1)));
	printf("%d\n", sizeof(a + 1));
	printf("%d\n", sizeof(*(a + 1)));
	printf("%d\n", sizeof(&a[0] + 1));
	printf("%d\n", sizeof(*(&a[0] + 1)));
	printf("%d\n", sizeof(*a));
	printf("%d\n", sizeof(a[3]));

    printf("%p\n",&a+1);

	return 0;
}

x86 Compilation result :

 x64 Compilation result :

  notes :

1.sizeof(a):a Is the name of a two-dimensional array ,sizeof( Array name ) It calculates the size of the entire array , The array size is 3*4*4=48 byte

2.sizeof(a[0][0]):a[0][0] Is the first element in the first row of a two-dimensional array , Size is 4 Bytes

3.sizeof(a[0]):a[0] Is the array name in the first row ,a[0] As an array, the list is placed alone in sizeof Inside , It calculates the size of the entire array , The size is 4*4=16 byte

4.sizeof(a[0] + 1):a[0] Is the array name in the first row , No, &, Not alone in sizeof Inside , therefore a[0] It represents the address of the first element , namely a[0][0] The address of ,a[0]+1 Is the address of the second element in the first line , As shown in the figure below , Yes, the address is 4/8 byte

5.sizeof(*(a[0] + 1)):a[0] + 1 Is the address of the second element in the first line ,*(a[0] + 1) Is the second element in the first line , The size is 4 Bytes

6.sizeof(a + 1):a Is the array name of a two-dimensional array , No, &, Not alone in sizeof Inside ,a Represents the address of the first element , The array name of a two-dimensional array is the address of the first element of the array , The address of the first element here is the address of the first line ,a+1 Is the address on the second line ( Here's the picture ), The type of int (*) [4], Yes, the address is 4/8 byte

7.sizeof(*(a + 1)):a + 1 Is the address of the second row of the two-dimensional array ,*(a + 1) Is the array name of the second row of the two-dimensional array ,*(a + 1) Equivalent to a[1],sizeof Inside is the array name , Calculate the size of the second line ,4*4=16 byte

8.sizeof(&a[0] + 1):a[0] Is the array name of the first row of the two-dimensional array ,&a[0] Is the address of the first row of the two-dimensional array ,&a[0] + 1 Is the address of the second row of the two-dimensional array , Yes, the address is 4/8 byte

9.sizeof(*(&a[0] + 1)):&a[0] + 1 Is the address of the second row of the two-dimensional array ,*(&a[0] + 1) Is the array name of the second row of the two-dimensional array , That is to say a[1],sizeof Inside is the array name , Calculate the size of the second line ,4*4=16 byte

10.sizeof(*a):a Is the array name of a two-dimensional array , Is the address of the first element of a two-dimensional array , The first element of a two-dimensional array is the address of the first row of elements ,*a Is the array name in the first row , That is to say a[0],sizeof Inside is the array name , It calculates the size of the first line ,4*4=16 byte

11.sizeof(a[3]):sizeof It doesn't really access the elements in parentheses , Instead, only its type is derived , So it feels a[3] Across the border , But it doesn't matter ,sizeof obtain a[3] The type is int [4],16 Bytes

12.&a+1:a Is the name of a two-dimensional array , The array name of a two-dimensional array is the address of the first element of the array , The address of the first element here is the address of the first line ,&a What you get is the address of the whole two-dimensional array ,&a+1 skip 3*4*4=48 Bytes , Point to the address behind the two-dimensional array .


10. Pointer written test questions

Pen test 1:
The output of the following code :
Code :
int main()
{
    int a[5] = { 1, 2, 3, 4, 5 };
    int *ptr = (int *)(&a + 1);
    printf( "%d %d\n", *(a + 1), *(ptr - 1));
    return 0; 
}

Running results :

  notes :

1.&a+1 Skip the whole a Array , Point to the address after the array , The type of int (*) [5]

2.(int*)(&a+1) Assign to a pointer variable ptr,ptr Or point to the address after the array , Type changed to int * type

3.ptr-1 Point to the last element of the array 5 The address of ,*(ptr-1) Get the element 5

4.a It's an array name , The array name is the first element address , The type is int*,*(a + 1) Is the second element of the array 2

Pen test 2:

p The value of is 0x100000. What are the values of the expressions in the following table ?
Structure Test The variable size of type is 20 Bytes

Code :

struct Test
{
 int Num;
 char *pcName;
 short sDate;
 char cha[2];
 short sBa[4];
}*p;

int main()
{
 p=(struct Test*)0x100000;
 printf("%p\n", p + 0x1);
 printf("%p\n", (unsigned long)p + 0x1);
 printf("%p\n", (unsigned int*)p + 0x1);
 return 0; 
}

Running results :

  notes :

1.p=(struct Test*)0x100000,0x100000 Itself is a hexadecimal number ,(struct Test*)0x100000 Put the... Of this hexadecimal number int Type to struct pointer type , At this point it is an address , Assign this address to p, At this time, the pointer variable p Point to 0x100000 This address

2.p + 0x1: Pointer to the variable +1 How many bytes to skip depends on the type of pointer variable ,int*+1 Skip four bytes ,char* +1 Skip a byte ,p yes struct Test* type , Add one to skip 20 Bytes , Pointing to the address 0x100014

3.(unsigned long)p + 0x1: here p Be coerced into unsigned long type ,p No longer a pointer type , It's an unsigned integer , here p The value of the inside 0x100000 It's a hexadecimal number ,(unsigned long)p + 0x1 by 0x100001

4.(unsigned int*)p+ 0x1: The pointer p Be coerced into unsigned int* type , Integer pointer +1 It's plus 4 Bytes ,(unsigned int*)p+ 0x1 Pointing to the address 0x100004

5. The numbers are in 0x Begin with a hexadecimal digit , The numbers are in 0 Begin with octal digits

6.%p Is printed as an address , Before the printed hexadecimal digit 0 No ellipsis

   %x Is to print hexadecimal digits , Before the printed hexadecimal digit 0 Will be omitted

   %p and %x All are unsigned ( This property is similar to %u be similar )

Pen test 3:

Code :

int main()
{
    int a[4] = { 1, 2, 3, 4 };
    int *ptr1 = (int *)(&a + 1);
    int *ptr2 = (int *)((int)a + 1);
    printf( "%x %x\n", ptr1[-1], *ptr2);
    return 0; 
}

Running results :

notes :

1.*ptr1 = (int *)(&a + 1):&a + 1 Skip the entire array a Point to the address after the array ,(int *)(&a + 1) The address's int * [4] Cast to int* type , At this time, the pointer variable ptr1 Pointing to the array a Back address , The type is int*

2. Print ptr1[-1]:ptr1[-1] Equivalent to *(ptr1-1),ptr1-1 Point to the last element of the array 4 The address of ,*(ptr1-1) obtain a The last element of the array 4

3.*ptr2 = (int *)((int)a + 1):(int)a,a It's an array name , Is the address of the first element of the array , Cast the address type to an integer , Get an integer number ;(int *)((int)a + 1), The address of the first element of the array is converted into an integer into a number, and then it is added and converted into a pointer type , It is equivalent to that the address of the first element of the array is moved back by one byte , Assign the moved address to *ptr2

vs Compiler is small end storage , The storage method of array is shown in the figure below :

01000000020000000300000004000000

Pointer to the variable ptr2 Pointing to 01 Next byte 00 The address of , The type of int* type , Yes ptr2 Dereference access 4 Bytes , The resulting hexadecimal digit is 0x02000000,%x Print out the previous 0 The result should be 2000000

Pen test 4:

Code :

int main()
{
	int a[3][2] = { (0, 1), (2, 3), (4, 5) };
	int* p;
	p = a[0];
	printf("%d", p[0]);
	return 0;
}

Running results :

notes :

1. The code array is assigned with parentheses + Comma expression ,a The array is shown in the figure below

13
50
00

2.a[0] Is the array name of the first row of the two-dimensional array , It is also the address of the first element in the first line , Pointer to the variable p Point to elements 1 The address of ,p[0] Equivalent to *(p+0) Equivalent to *p, So the printed value is 1

Pen test 5:

Code :

int main()
{
	int a[5][5];
	int(*p)[4];
	p = a;
	printf("%p %d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
	return 0;
}

Running results :

  notes :

1. Two dimensional array a As shown in the figure below

01234

2.int(*p)[4]:p It's an array pointer ,p The array that can be pointed to is 4 An integer element ,p+1 Will skip 4 An integer element 16 Bytes

3.p[4][2]:p There is a two-dimensional array a The address of , That is to say a The address of the first element of is the address of the first line element .p[4][2] Equivalent to *(*(p+4)+2);*(p+4), Pointer to the variable p yes int * [4] type ,p+4 skip 16 An integer element is then dereferenced 4 The integer elements are shown in the following figure

01234

*(p+4) Equivalent to the array name of the four integer elements accessed , The array name is the address of the first element of the four elements ,*(p+4)+2 Yes

this 4 The third of the elements 3 Addresses of elements ,*(*(p+4)+2) It points to the third of the four elements , As shown in the figure below

01234

therefore p[4][2] It is the red square element in the above figure ,&p[4][2] Is the address of the element

4.a[4][2] It's number one in the array 5 Xing di 3 Elements , As shown in the figure below

01234

therefore a[4][2] It is the red square element in the above figure ,&a[4][2] Is the address of the element

5. &p[4][2] - &a[4][2]: Subtract two integer addresses , What you get is between two addresses int Number of elements , Because it is a small address minus a large address , So the result is -4

01234

6.-4 The original code of :10000000000000000000000000000100

   -4 The inverse of :11111111111111111111111111111011

   -4 Complement :11111111111111111111111111111100

   -4 The hexadecimal complement is (%p Print ):ff ff ff fc 

Pen test 6:

Code :

int main()
{
	int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	int* ptr1 = (int*)(&aa + 1);
	int* ptr2 = (int*)(*(aa + 1));
	printf("%d %d\n", *(ptr1 - 1), *(ptr2 - 1));
	return 0;
}

Running results :

  notes :

1.int* ptr1 = (int*)(&aa + 1):&aa+1 Skip the entire array and point to the address after the array , Cast the address to int* Type and assign to ptr1. Pointer to the variable ptr1 Point to the address of the element behind the array , The type is int*

2.*(ptr1 - 1):ptr1-1 Points to the address of the last element of the array , Dereference it to get the last element of the array 10

3.int* ptr2 = (int*)(*(aa + 1)):aa Is the array name of a two-dimensional array , Is the address of the first element of the two-dimensional array ;aa + 1 Skip the first line , Address pointing to the second line , The type of int * (5);*(aa + 1) Get the array name in the second row of the two-dimensional array , It is also equivalent to the address of the first element in the second line , So we get the first element of the second line 6 The address of ;(int*)(*(aa + 1)) Here the cast type is cast to int* Type is redundant , Because it is int* type ; take (int*)(*(aa + 1)) Assign to a pointer variable ptr2,ptr2 Point to the first element of the second row of the two-dimensional array 6 The address of , The type is int * type .

4.*(ptr2 - 1):ptr2-1 Points to a two-dimensional array element 5 The address of , Dereference it to get the element 5

Pen test 7:

Code :

int main()
{
	char* a[] = { "work","at","alibaba" };
	char** pa = a;
	pa++;
	printf("%s\n", *pa);
	return 0;
}

Running results :

notes :

1. Pointer array a And secondary pointer variables pa The relationship is shown in the figure below

2. Secondary pointer variables pa The type of char** type , Its pointing object is char* type , therefore pa+1 Or dereference skip or access 4 Bytes ,pa++ Point to the second element of the pointer array ,*pa It's an array of pointers a The second element of , Pointer array a The second element of is the string "at" The address of , So pass parameters to the print function *pa It's equivalent to passing "at" The address of the string is the array name , The result of printing is at

Pen test 8:

Code :

int main()
{
	char* c[] = { "ENTER","NEW","POINT","FIRST" };
	char** cp[] = { c + 3,c + 2,c + 1,c };
	char*** cpp = cp;
	printf("%s\n", **++cpp);
	printf("%s\n", *-- * ++cpp + 3);
	printf("%s\n", *cpp[-2] + 3);
	printf("%s\n", cpp[-1][-1] + 1);
	return 0;
}

Running results :

  notes :

1. Pointer array c、 Secondary pointer variables cp And three-level pointer variables cpp The relationship is shown in the figure below

2.**++cpp:cpp Now point to cp The first element address ;++cpp Skip one char** The elements of 4 Bytes , Point to cp The second element address ;*++cpp obtain cp The second element , The element is c+2, It's a pointer array c The address of the third element ;**++cpp Get the pointer array c The third element of , The element is a string "POINT" The address of ; Pass the address of the string to printf Function to print ( Be careful :**++cpp Code execution finished ,cpp Deposit is cp The address of the second element , Yes cp The second element of )

3.*-- * ++cpp + 3:cpp Now point to cp The second element address ;++cpp Skip one char** The elements of 4 Bytes , Point to cp The third element address ;* ++cpp obtain cp The third element , The element is c+1, It's a pointer array c The address of the second element ;-- * ++cpp by cp The third element -1, namely c+1-1=c, That is, an array of pointers c The address of the first element ;*-- * ++cpp Get the pointer array c The first element of , The element is a string "ENTER" The address of ;*-- * ++cpp + 3 Points to the string "ENTER" In the character 'E' The address of ; In the string 'E' Send the address of to printf Function to print ( Be careful :*-- * ++cpp + 3 Code execution finished ,cpp Deposit is cp The address of the third element , Yes cp The third element of )

4.*cpp[-2] + 3:cpp[-2] Equivalent to *(cpp-2),cpp Itself points to cp The third element ,cpp-2 Yes cp First element ,*(cpp-2) Got it cp First element , The element is c+3, It's a pointer array c The address of the fourth element ;*cpp[-2] Get the pointer array c The fourth element of , The element is a string "EIRST" The address of ;*cpp[-2] + 3 Points to the string "FIRST" In the character 'S' The address of ; In the string 'S' Send the address of to printf Function to print ( Be careful :*cpp[-2] + 3 Code execution finished ,cpp Deposit is cp The address of the third element remains unchanged , Yes cp The third element of )

5.cpp[-1][-1] + 1:cpp[-1][-1] Equivalent to *(*(cpp-1)-1),cpp Itself points to cp The third element ,cpp-1 Yes cp The second element ,*(cpp-1) Got it cp The second element , The element is c+2, It's a pointer array c The address of the third element ,*(cpp-1)-1 by cp The second element -1, namely c+2-1=c+1, That is, an array of pointers c The address of the second element ,*(*(cpp-1)-1) Get the pointer array c The second element of , The element is a string "NEW" The address of ;cpp[-1][-1] + 1 Points to the string "NEW" In the character 'E' The address of ; In the string 'E' Send the address of to printf Function to print

原网站

版权声明
本文为[Stretch the curtain with the wind]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202280520088454.html