C language advanced pointer advanced

Please add a picture description


The topic of pointers, we have already touched on the C language elementary blog, we know the concept of pointers:

  1. A pointer is a variable used to store an address, which uniquely identifies a piece of memory space.
  2. The pointer size is fixed at 4/8 bytes (32-bit platform/64-bit platform).
  3. The pointer has a type, and the type of the pointer determines the step size of the pointer ± integer, and the authority of the pointer dereference operation.
  4. Arithmetic with pointers.
    Next, let's move on to the advanced topic of pointers

1. Character pointer

In the pointer type, we know that there is a pointer type that is a character pointer char*;
generally used:

int main()
{
    
    
 	char ch = 'a';
 	char *pc = &ch;
 	*pc = 'a';
 	return 0;
}

Another way to use it is as follows:

int main()
{
    
    
 	const char* pstr = "hello C.";
 	printf("%s\n", pstr);
 	return 0;
}

So is a string put into the pstr pointer variable here?
In fact, it is not, here is actually storing the address of the first character of the string, that is, h, into the pointer variable pstr.

Let's take a look at the following interview question about character pointers

#include <stdio.h>
int main()
{
    
    
	char str1[] = "hello bit.";
	char str2[] = "hello bit.";
	const char* str3 = "hello bit.";
	const char* str4 = "hello bit.";
	if (str1 == str2)
		printf("str1 and str2 are same\n");
	else
		printf("str1 and str2 are not same\n");

	if (str3 == str4)
		printf("str3 and str4 are same\n");
	else
		printf("str3 and str4 are not same\n");

	return 0;
}

insert image description here
First of all, the array name represents the address of the first element of the array, so here str1 and str2 respectively store the address of the first character of the corresponding array, they are not the same, so the first output result is str1 and str2 are not same, here str3 and str4 Points to the same constant string. C/C++ will store constant strings in a separate memory area. When several pointers point to the same string, they will actually point to the same block of memory. But when using the same constant string to initialize different arrays, different memory blocks will be opened up. So str1 and str2 are different, and str3 and str4 are the same.

2. Array of pointers

We have talked about pointer arrays in the beginning of C language,
as follows:

int* arr1[10]; //整形指针的数组
char *arr2[4]; //一级字符指针的数组
char **arr3[5];//二级字符指针的数组

3. Array pointer

3.1 Definition of array pointer

Array pointers are pointers? Or an array?
The answer is: pointers.
We are already familiar with:
Integer pointer: int * p; A pointer that can point to integer data.
Floating-point pointer: float * pf; A pointer that can point to floating-point data.
The array pointer should be: a pointer that can point to an array.
So which of the following codes is an array pointer?

int *p1[10];
int (*p2)[10];

The answer is int (*p2)[10];

p is first combined with *, indicating that p is a pointer variable, and then it points to an array of 10 integers. So p is a pointer pointing to an array, called an array pointer.

It should be noted that the priority of [] is higher than that of *, so () must be added to ensure that p is combined with * first

3.2 & array name VS array name

What are the arrays
arr and &arr respectively?
We know that arr is the name of the array, and the array name represents the address of the first element of the array.
What is the &arr array name?

We know that arr is the name of the array, and the array name represents the address of the first element of the array.
What is the &arr array name?
Let's look at a piece of code:

#include <stdio.h>
int main()
{
    
    
 int arr[10] = {
    
    0};
 printf("%p\n", arr);
 printf("%p\n", &arr);
 return 0;
}

insert image description here
We can see that the addresses printed by the array name and & array name are the same, are they the same?
Look at the next piece of code:

#include <stdio.h>
int main()
{
    
    
	int arr[10] = {
    
     0 };
	printf("arr = %p\n", arr);
	printf("&arr= %p\n", &arr);
	printf("arr+1 = %p\n", arr + 1);
	printf("&arr+1= %p\n", &arr + 1);
	return 0;
}

insert image description here
According to the above code, we found that, in fact, &arr and arr have the same value, but the meaning should be different.
In fact : &arr represents the address of the array, not the address of the first element of the array. (Experience in detail)
The type of &arr in this example is : int(*)[10], which is an array pointer type, the address of the array +1, skipping the size of the entire array, so &arr+1 is relative to &arr The difference is 40

3.3 Use of array pointers

How is the array pointer used?
Since the array pointer points to an array, the address of the array should be stored in the array pointer.
Look at the code:

#include <stdio.h>
int main()
{
    
    
	int arr[10] = {
    
     1,2,3,4,5,6,7,8,9,0 };
	int(*p)[10] = &arr;
	return 0;
}

Assign the address of the array arr to the array pointer variable p, but we generally seldom write code like this
as follows:

#include <stdio.h>
void print_arr1(int arr[3][5], int row, int col)
{
    
    
	int i = 0;
	for (i = 0; i < row; i++)
	{
    
    
		for (j = 0; j < col; j++)
		{
    
    
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}
}
void print_arr2(int(*arr)[5], int row, int col)
{
    
    
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
    
    
		for (j = 0; j < col; j++)
		{
    
    
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}
}
int main()
{
    
    
	int arr[3][5] = {
    
     1,2,3,4,5,6,7,8,9,10 };
	print_arr1(arr, 3, 5);
	print_arr2(arr, 3, 5);
	return 0;
}

The array name arr indicates the address of the first element,
but the first element of the two-dimensional array is the first row of the two-dimensional array,
so the arr passed here is actually equivalent to the address of the first row, which is the address of the one-dimensional array and
can be received by an array pointer

Let's take a look at what the following codes represent

int arr[5];//数组
int *parr1[10];//指针数组
int (*parr2)[10];//数组指针
int (*parr3[10])[5];//数组指针数组

4. Array parameters, pointer parameters

4.1 One-dimensional array parameter passing

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);
}

These delivery methods are all possible

4.2 Two-dimensional array parameter passing

void test(int arr[3][5])//ok
{
    
    }
void test(int arr[][])//不可以
{
    
    }
void test(int arr[][5])//ok
{
    
    }
void test(int* arr)//不可以
{
    
    }
void test(int* arr[5])//ok
{
    
    }
void test(int(*arr)[5])//ok
{
    
    }
void test(int** arr)//不可以
{
    
    }
int main()
{
    
    
	int arr[3][5] = {
    
     0 };
	test(arr);
}

Summary: When passing parameters in a two-dimensional array, the design of function parameters can only omit the first [] number.
Because for a two-dimensional array, you don't need to know how many rows there are, but you must know how many elements are in one row. This is convenient for operation.

4.3 First-level pointer parameter passing

#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]);
	print(p, sz);
	return 0;
}

4.4 Second-level pointer parameter passing

#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;
}

5. Function pointers

Look at the code first

#include <stdio.h>
void test()
{
    
    
	printf("hehe\n");
}
int main()
{
    
    
	printf("%p\n", test);
	printf("%p\n", &test);
	return 0;
}

insert image description here
It is not difficult to see that the function name is the function address, and these two addresses are the addresses of the test function. So how do we save the address of our function if we want to save it?

#include <stdio.h>
void test()
{
    
    
	printf("hehe\n");
}
void (*pfun1)();

pfun1 is first combined with *, indicating that pfun1 is a pointer, and the pointer points to a function, the pointed function has no parameters, and the return value type is void.

6. Array of function pointers

An array is a storage space that stores the same type of data, so we have already learned about arrays of pointers, for example:

int *arr[10];
//数组的每个元素是int*

Then store the address of the function in an array, then this array is called an array of function pointers, how to define the array of function pointers?

int (*parr1[10])();

Parr1 is first combined with [], indicating that parr1 is an array, what is the content of the array? is a function pointer of type int (*)().
Purpose of function pointer array: Transfer table
Example: Calculator conventional writing

#include <stdio.h>
int add(int a, int b)
{
    
    
	return a + b;
}
int sub(int a, int b)
{
    
    
	return a - b;
}
int mul(int a, int b)
{
    
    
	return a * b;
}
int div(int a, int b)
{
    
    
	return a / b;
}
int main()
{
    
    
	int x, y;
	int input = 1;
	int ret = 0;
	do
	{
    
    
		printf("*************************\n");
		printf(" 1:add 2:sub \n");
		printf(" 3:mul 4:div \n");
		printf("*************************\n");
		printf("请选择:");
		scanf("%d", &input);
		switch (input)
		{
    
    
		case 1:
			printf("输入操作数:");
			scanf("%d %d", &x, &y);
			ret = add(x, y);
			printf("ret = %d\n", ret);
			break;
		case 2:
			printf("输入操作数:");
			scanf("%d %d", &x, &y);
			ret = sub(x, y);
			printf("ret = %d\n", ret);
			break;
		case 3:
			printf("输入操作数:");
			scanf("%d %d", &x, &y);
			ret = mul(x, y);
			printf("ret = %d\n", ret);
			break;
		case 4:
			printf("输入操作数:");
			scanf("%d %d", &x, &y);
			ret = div(x, y);
			printf("ret = %d\n", ret);
			break;
		case 0:
			printf("退出程序\n");
			break;
		default:
			printf("选择错误\n");
			break;
		}
	} while (input);

	return 0;

Implementation using an array of function pointers:

#include <stdio.h>
int add(int a, int b)
{
    
    
	return a + b;
}
int sub(int a, int b)
{
    
    
	return a - b;
}
int mul(int a, int b)
{
    
    
	return a * b;
}
int div(int a, int b)
{
    
    
	return a / b;
}
int main()
{
    
    
	int x, y;
	int input = 1;
	int ret = 0;
	int(*p[5])(int x, int y) = {
    
     0, add, sub, mul, div }; //转移表
while(input)
{
    
    
	printf("*************************\n");
	printf(" 1:add 2:sub \n");
	printf(" 3:mul 4:div \n");
	printf("*************************\n");
	printf("请选择:");
	scanf("%d", &input);
	if ((input <= 4 && input >= 1))
	{
    
    
		printf("输入操作数:");
		scanf("%d %d", &x, &y);
		ret = (*p[input])(x, y);
	}
	else
		printf("输入有误\n");
	printf("ret = %d\n", ret);
}
return 0;
}

This way the code is not redundant

7. Pointer to array of function pointers

A pointer to an array of function pointers is a pointer , and the pointer points to an array , and the elements of the array are all function pointers ;
then how to define it, see the following code:

void test(const char* str)
{
    
    
	printf("%s\n", str);
}
int main()
{
    
    
	//函数指针pfun
	void (*pfun)(const char*) = test;
	//函数指针的数组pfunArr
	void (*pfunArr[5])(const char* str);
	pfunArr[0] = test;
	//指向函数指针数组pfunArr的指针ppfunArr
	void (*(*ppfunArr)[5])(const char*) = &pfunArr;
	return 0;
}

8. Callback function

A callback function is a function that is called through a function pointer. If you pass a function pointer (address) as a parameter to another function, when this pointer is used to call the function it points to, we say this is a callback function. The callback function is not directly called by the implementer of the function, but is called by another party when a specific event or condition occurs, and is used to respond to the event or condition.

Let's take the qsort function of the library function as an example, let's look at the definition of this function first

_ACRTIMP void __cdecl qsort(
    _Inout_updates_bytes_(_NumOfElements * _SizeOfElements) void*  _Base,
    _In_                                                    size_t _NumOfElements,
    _In_                                                    size_t _SizeOfElements,
    _In_                _CoreCrtNonSecureSearchSortCompareFunction _CompareFunction
    );

insert image description here
The first formal parameter is void* because it can accommodate pointers of any type. The
last _CoreCrtNonSecureSearchSortCompareFunction _CompareFunction is actually a callback function. When we use the qsort function, we need to write another _CompareFunction function to sort different types. .
Example:

#include<stdlib.h>
#include <stdio.h>
int int_cmp(const void* p1, const void* p2)
{
    
    
	return (*(int*)p1 - *(int*)p2);
}
int main()
{
    
    
	int arr[] = {
    
     1, 3, 5, 7, 9, 2, 4, 6, 8, 0 };
	int i = 0;

	qsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof(int), int_cmp);
	for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
	{
    
    
		printf("%d ", arr[i]);
	}
	printf("\n");
	return 0;
}

Among them, the int_cmp function is _CoreCrtNonSecureSearchSortCompareFunction _CompareFunction called by qsort
insert image description here
. It should be noted that this default writing method is generally in ascending order. If you want to change it to descending order, you can swap p1 and p2, as shown in the following code:

int int_cmp(const void* p1, const void* p2)
{
    
    
	return (*(int*)p2 - *(int*)p1);
}

Let's look at the sorting of the structure array

#include<stdlib.h>
#include <stdio.h>
#include <string.h>
struct Stu
{
    
    
	char name[20];
	int age;
};

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

void test1()
{
    
    
	struct Stu arr[] = {
    
     {
    
    "zhangsan", 20}, {
    
    "lisi", 50},{
    
    "wangwu", 15} };
	int sz = sizeof(arr) / sizeof(arr[0]); 
	printf("初始序列:> ");
	for (int i = 0; i < sz; i++)
	{
    
    
		printf("%s,%d     ", arr[i].name, arr[i].age);
	}
	printf("\n");
	qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_age);
	printf("按年龄排序:> ");
	for (int i = 0; i < sz; i++)
	{
    
    
		printf("%s,%d     ", arr[i].name, arr[i].age);
	}
	printf("\n");
}

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

void test2()
{
    
    
	struct Stu arr[] = {
    
     {
    
    "zhangsan", 20}, {
    
    "lisi", 50},{
    
    "wangwu", 15} };
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_name);
	printf("按名字排序:> ");
	for (int i = 0; i < sz; i++)
	{
    
    
		printf("%s,%d     ", arr[i].name, arr[i].age);
	}
}

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

insert image description here
According to the same principle, we can also write a bubble sort callback function that adapts to multiple types
Example:

#include<stdio.h>
void Swap(void* p1, void* p2, int size)
{
    
    
	for (int i = 0; i < size; i++)
	{
    
    
		char tmp = *((char*)p1 + i);
		*((char*)p1 + i) = *((char*)p2 + i);
		*((char*)p2 + i) = tmp;
	}
}
void Bubble_Sort(void* base, int num, int size, int(*cmp)(void*,void*))
{
    
    
	int i = 0;
	int j = 0;
	for (i = 0; i < num - 1; i++)
	{
    
    
		for (j = 0; j < num - i - 1; j++)
		{
    
    
			if (cmp((char*)base + j * size, (char*)base + (j + 1) * size) > 0)
				Swap((char*)base + j * size, (char*)base + (j + 1) * size,size);
		}
	}
}

int Int_Sort(const void* p1, const void* p2)
{
    
    
	return *(int*)p1 - *(int*)p2;
}
void Int_Print(int* arr,int sz)
{
    
    
	for (int i = 0; i < sz; i++)
		printf("%d ", arr[i]);
}

void Test1()
{
    
    
	int arr[] = {
    
     7,6,5,4,8,9,3,1,2 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	printf("初始序列:> ");
	Int_Print(arr, sz);
	printf("\n");
	Bubble_Sort(arr, sz, sizeof(arr[0]), Int_Sort);
	printf("排序后  :> ");
	Int_Print(arr,sz);
}

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

insert image description here

9. Analysis of pointer and array pen test questions

All the following codes are compiled for 64 platform

9.1 One-dimensional arrays

int a[] = {
    
    1,2,3,4};
printf("%d\n",sizeof(a));//sizeof中数组名代表整个数组
printf("%d\n",sizeof(a+0));//数组名+0为第一个元素的地址,也就是指针,指针大小就是4/8个字节,当前为64位,所以是8
printf("%d\n",sizeof(*a));//对数组名进行解引用操作,获取指向数组第一个元素
printf("%d\n",sizeof(a+1));//a+1代表第二个元素的地址
printf("%d\n",sizeof(a[1]));//代表第二个元素
printf("%d\n",sizeof(&a));//对数组名取地址,代表的是指针
printf("%d\n",sizeof(*&a));//&再*解引用等于没做操作,还是整个数组
printf("%d\n",sizeof(&a+1));//对数组名取地址再+1代表的是该数组之后的地址
printf("%d\n",sizeof(&a[0]));//代表第一个元素的地址
printf("%d\n",sizeof(&a[0]+1));//代表第二个元素的地址

insert image description here

9.2 Character arrays

char arr[] = {
    
    'a','b','c','d','e','f'};
printf("%d\n", sizeof(arr));//整个数组
printf("%d\n", sizeof(arr+0));//数组名+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));//代表第二个元素的地址

insert image description here

char arr[] = {
    
     'a','b','c','d','e','f' };
printf("%d\n", strlen(arr));//因为字符数组arr中没有\0,所以在求字符串长度的时候,会一直往后找,产生的结构就是随机值
printf("%d\n", strlen(arr+0));//arr + 0是首元素的地址,和第一个一样,也是随机值
//printf("%d\n", strlen(*arr));//错误, arr是数组首元素的地址,*arr就是数组首元素,就是'a'-97
//strlen函数参数的部分需要传一个地址,当我们传递的是'a'时,'a'的ASCII码值是97,那就是将97作为地址传参
//strlen就会从97这个地址开始统计字符串长度,这就非法访问内存了
//printf("%d\n", strlen(arr[1]));//错误,同上,只不过这里传的是第二个元素b
printf("%d\n", strlen(&arr));//&arr是数组的地址,数组的地址和数组首元素的地址,值是一样的,那么传递给strlen函数后,依然是从数组的第一个元素的位置开始往后统计
printf("%d\n", strlen(&arr+1));//随机值-6,减去了上面6个元素的长度
printf("%d\n", strlen(&arr[0]+1));//&arr[0] + 1是第二个元素的地址。结果也是随机值

insert image description here

char arr[] = "abcdef";
printf("%d\n", sizeof(arr));//整个数组
printf("%d\n", sizeof(arr + 0));//arr + 0是首元素的地址
printf("%d\n", sizeof(*arr));//*arr其实就是首元素,1个字节
printf("%d\n", sizeof(arr[1]));//arr[1]是第二个元素,1个字节
printf("%d\n", sizeof(&arr));//&arr是数组的地址,是地址就是4/8个字节
printf("%d\n", sizeof(&arr + 1));//&arr + 1是跳过一个数组的地址,4/8
printf("%d\n", sizeof(&arr[0] + 1));//&arr[0] + 1是第二个元素的地址 4/8

insert image description here

char arr[] = "abcdef";
printf("%d\n", strlen(arr));//整个字符串的长度
printf("%d\n", strlen(arr+0));//首元素的地址开始,所以结果同上
//printf("%d\n", strlen(*arr));//错误, arr是数组首元素的地址,*arr就是数组首元素
//printf("%d\n", strlen(arr[1]));//错误,同上,只不过这里传的是第二个元素b
printf("%d\n", strlen(&arr));//整个数组的地址,还是从首元素开始
printf("%d\n", strlen(&arr+1));//整个数组后开始计算,所以是随机值
printf("%d\n", strlen(&arr[0]+1));//从第二个元素地址开始算

insert image description here

9.3 Character Pointers

It can also be said to be an array of characters, and the array itself is also a pointer

char *p = "abcdef";
printf("%d\n", sizeof(p));//p为指针变量,大小为4/8
printf("%d\n", sizeof(p+1));//p+1是'b'的地址
printf("%d\n", sizeof(*p));//*p 就是字符a
printf("%d\n", sizeof(p[0]));//同上
printf("%d\n", sizeof(&p));//*p的地址
printf("%d\n", sizeof(&p+1));//*p之后的地址
printf("%d\n", sizeof(&p[0]+1));//&p[0] + 1得到是'b'的地址

insert image description here

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));//从第二个字符开始算

insert image description here

9.4 Two-dimensional arrays

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));
//a[0]作为第一行的数组名,没有单独放在sizeo内部,没有&
//a[0]表示数组首元素的地址,也就是a[0][0]的地址
//所以a[0]+1是第一行第二个元素的地址,是地址就是4/8个字节

insert image description here

int a[3][4] = {
    
     0 };
printf("%d\n", sizeof(*(a[0] + 1)));//计算的是就是第一行第2个元素的大小
printf("%d\n", sizeof(a + 1));//a是数组首元素的地址,是第一行的地址 int(*)[4],a+1 就是第二行的地址
printf("%d\n", sizeof(*(a + 1)));//计算的是第二行的大小
printf("%d\n", sizeof(&a[0] + 1));//&a[0]是第一行的地址 int(*)[4],&a[0]+1 是第二行的地址 int(*)[4]
printf("%d\n", sizeof(*(&a[0] + 1)));//计算的是第二行的大小
printf("%d\n", sizeof(*a));//计算的是第一行的大小
printf("%d\n", sizeof(a[3]));//计算的是一行的大小,并不存在越界,因为实际并没有访问内存

insert image description here
Summary :
The meaning of the array name:

  1. sizeof(array name), where the array name represents the entire array, and the calculation is the size of the entire array.
  2. &Array name, where the array name represents the entire array, and the address of the entire array is taken out.
  3. In addition, all array names represent the address of the first element.

10. Pointer pen test questions

10.1 Written test question 1

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

What is the outcome of the procedure?
insert image description here
The second element accessed by *(a + 1), *ptr is the address after skipping the entire array

10.2 Written Test Question 2

struct Test
{
    
    
	int Num;
	char* pcName;
	short sDate;
	char cha[2];
	short sBa[4];
}*p= (struct Test*)0x10000000;
int main()
{
    
    
	printf("%p\n", p + 0x1);
	printf("%p\n", (unsigned long)p + 0x1);
	printf("%p\n", (unsigned int*)p + 0x1);
	return 0;
}

Suppose the value of p is 0x10000000. What are the values ​​of the following expressions?
It is known that the variable size of the structure Test type is 20 bytes.
insert image description here
The first result is to skip the entire structure, so add 20 directly, and the address is printed in hexadecimal, so it is 10000014. The
second result is to first add The address of the structure is converted to a long integer, and the calculation of the integer is directly added by 1. The
third result is to first convert the address of the structure into a pointer, and adding 1 skips the size of a pointer, that is, 4/8 bytes

10.3 Written test question 3

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

insert image description here
insert image description here

10.4 Written Test Question 4

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

insert image description here
It should be noted here that during initialization, we only initialized the first 3 values, because there are () instead of {}, so only the numbers in the comma expression, that is, 1, 3, 5 , and then all should be 0; so when printing the value pointing to the first line, only print a[0][0], which is 1.

10.5 Written test question 5

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;
}

insert image description here
insert image description here

10.6 Written test question 6

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", *(ptr1 - 1), *(ptr2 - 1));
	return 0;
}

insert image description here
&aa+1 skips the entire array, so -1, the printed integer value is the last element of the aa array
aa+1 skips the first line of the two-dimensional array, which is the starting address of 6, so - 1. The printed integer value is the last element of the first line of the aa array

10.7 Written test question 7

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

insert image description here
First of all, char* a[] stores the address of the first three letters, and char** pa stores the address of the first element w in the pointer array, so pa++, pa points to the address of the second element a, dereferencing After printing is at.

10.8 Written Test Question 8

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;
}

insert image description here
insert image description here

epilogue

Interested friends can pay attention to the author, if you think the content is good, please give a one-click triple link, you crab crab! ! !
It is not easy to make, please point out if there are any inaccuracies
Thank you for your visit, UU watching is the motivation for me to persevere.
With the catalyst of time, let us all become better people from each other! !
insert image description here

Guess you like

Origin blog.csdn.net/kingxzq/article/details/131613390