C/C++ 操作数组与指针笔记

C/C++
326
0
0
2023-02-14

指针数组:

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

void PrintInt()
{
	int x = 10,y = 20,z = 30;

	int *Array[] = { &x, &y, &z };   // 定义数组指针
	*Array[0] = 100;                 // 给x重新赋值
	*Array[2] = 300;                 // 给z重新赋值

	for (int x = 0; x < 3; x++)
		printf("地址: %x --> 数值:%d \n", Array[x], *(Array[x]));
}

void PrintArray()
{
	int x[] = { 1, 2, 3, 4, 5 };
	int y[] = { 6, 7, 8, 9, 10 };

	int *Array[] = { &x, &y };

	// printf("%d \n", *(Array[0] + 1));
	for (int x = 0; x < 2; x++)
	{
		for (int y = 0; y < 5; y++)
		{
			printf("地址: %x --> 数值: %d \n", Array[x] + y, *(Array[x] + y));
		}
	}
}

int main(int argc, char* argv[])
{
	PrintArray();

	system("pause");
	return 0;
}

指针取步长:

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

struct Person
{
	int num;
	char name[64];
	int age;
};

int main(int argc, char* argv[])
{
	char buf[100] = { 0 };
	int num = 100;
	// 在buf+1的位置拷贝字符串.
	memcpy(buf + 1, &num, sizeof(int));

	char *ptr = buf;
	// (int *) => 取多少个字节 / ptr+1 遍历到下一个数据上
	int tmp = *(int *)(ptr + 1);
	printf("取出buf里面的int数据: %d \n", tmp);

	struct Person sp = { 1, "lyshark", 22 };
	printf("age相对于Person首地址偏移量: %d\n", offsetof(struct Person, age));

	// 定位到age的内存: (char *)&p + offsetof(struct Person,age)
	// 整体括起来取首地址: ((char *)&p + offsetof(struct Person,age))
	// 强制取出四字节数据: (int *)((char *)&p + offsetof(struct Person,age))

	int struct_age = *(int *)((char *)&sp + offsetof(struct Person, age));
	printf("结构体中age的数据是: %d \n", struct_age);
	
	system("pause");
	return 0;
}

指针间接赋值:

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

void ChangeValue(int *p)
{ // 改变某个值
	(*p) = 200;
}

void ChangePointer(int **val)
{ // 改变指针的值
	*val = 0x08;
}

int main(int argc, char* argv[])
{
	int num = 100;
	ChangeValue(&num);
	printf("改写后的数值: %d 当前地址: %x \n", num,&num);

	int *p = NULL;
	ChangePointer(&p);
	printf("当前p地址: %x \n", p);

	system("pause");
	return 0;
}

指针做函数参数: 指针的输入和输出特性

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

void Print(const char *str)
{
	printf("输出指针内容: %s \n", str + 2);
}

int main(int argc, char* argv[])
{
	char *ptr = malloc(sizeof(char)* 100);
	memset(ptr, 0, 100); // 初始化内存
	
	strcpy(ptr, "hello lyshark");
	Print(ptr);

	system("pause");
	return 0;
}
#include <stdio.h>
#include <stdlib.h>

void Print(char **Array,int len)
{
	// Array[0] = *(Array +0)
	for (int x = 0; x < len; x++)
	{
		printf("首地址: 0x%x 参数: %s \n", *(Array + x),Array[x]);
	}
}

int main(int argc, char* argv[])
{
	char *str[] = { "admin", "guest", "lyshark", "root" };

	int str_len = sizeof(str) / sizeof(str[0]);
	Print(str, str_len);

	system("pause");
	return 0;
}

指针做函数参数: 输出特性

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

void allocateSpace(char **tmp)
{
	char *p = malloc(100);
	memset(p, 0, 100);
	strcpy(p, "hello lyshark");
	*tmp = p;  // 将指针甩出去
}

int main(int argc, char* argv[])
{
	char *p = NULL;
	allocateSpace(&p);

	printf("输出数据: %s", p);

	if (p != NULL)
	{
		free(p);
		p = NULL;
	}

	system("pause");
	return 0;
}

堆指针分配:

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

int main(int argc, char* argv[])
{
	int *p = calloc(10, sizeof(int));
	for (int x = 0; x < 10; x++)
	{
		p[x] = x + 1;
	}

	for (int x = 0; x < 10; x++)
		printf("%d \n", p[x]);

	if (p != NULL)
	{
		free(p);
		p = NULL;
	}

	system("pause");
	return 0;
}

Realloc:

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

int main(int argc, char* argv[])
{
	int *p = malloc(sizeof(int)* 10); // 分配空间

	for (int x = 0; x < 10; x++)
	{
		p[x] = x;
		printf("%d \n", p[x]);
	}

	int old_ptr = p;
	p = realloc(p, sizeof(int)* 20);
	int new_ptr = p;

	// realloc 函数追加空间,如果空间够用则直接追加.
	// 如果空间不够用了,那么将会重新分配一块空间,并将原数据拷贝到新的地址上
	// 随后会自动释放旧的空间
	if (old_ptr != new_ptr)
		printf("原始空间: 0x%x 新空间: 0x%x \n", old_ptr, new_ptr);
	else
		printf("原始空间: 0x%x 够用,并没有发生变化.\n");

	system("pause");
	return 0;
}

const 使用场景 高效传递,一般为了高效,我们使用地址传递,这样就无须重复拷贝了。

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

struct Student
{
	int num;
	char *name;
};


void MyPrint(const struct Student *stu)
{

	// const 常量无法修改了,适合于打印数据,骚操作可以修改
	struct Student *p = (struct Student *)stu;
	p->num = 100;

	printf("内部的打印: %d \n", stu->num);
}

int main(int argc, char* argv[])
{
	struct Student stu = { 1, "lyshark" };
	// 传递指针要比传递参数效率更高 MyPrint(stu) --> MyPrint(&stu);
	MyPrint(&stu);
	printf("外部的打印: %d \n", stu.num);

	system("pause");
	return 0;
}

多级指针:

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

int main(int argc, char* argv[])
{
	int num = 10;

	int *ptr = &num;

	int **ptr1 = &ptr;

	**ptr1 = 12;

	printf("%d", **ptr1);
	system("pause");
	return 0;
}

二级指针(输出特性1):

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


void allocateSpace(int **tmp)
{
	int * arr = malloc(sizeof(int)* 10);
	for (int x = 0; x < 10; x++)
		arr[x] = x;

	// 指针间接赋值
	*tmp = arr;
}

void PrintArray(int *tmp)
{
	for (int x = 0; x < 10; x++)
		printf("%d ", tmp[x]);
}

void freeSpace(int **tmp)
{
	free(*tmp);
	*tmp = NULL;
	tmp = NULL;
}

int main(int argc, char* argv[])
{
	int *pArray = NULL;

	allocateSpace(&pArray);
	PrintArray(pArray);

	freeSpace(&pArray);


	if (pArray == NULL)
		printf("已释放,被掏空 \n");



	system("pause");
	return 0;
}

二级指针做函数参数 输入特性1

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

void PrintArray(const int **tmp)
{
	for (int x = 0; x < 10; x++)
	{
		printf("%d ", *tmp[x]);
	}
}

int main(int argc, char* argv[])
{
	int ary[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

	// 堆区分配指针,接收指针(地址)的指针
	int **pArray = malloc(sizeof(int *)* 10);

	for (int x = 0; x < 10; x++)
		//pArray[x] = &ary[x];
		*(pArray + x) = &ary[x];

	PrintArray(pArray);

	system("pause");
	return 0;
}

二级指针做函数参数 输入特性2

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

void PrintArray(const int **tmp)
{
	for (int x = 0; x < 10; x++)
	{
		printf("%d ", *tmp[x]);
	}
}


int main(int argc, char* argv[])
{

	int **pArray = malloc(sizeof(int *)* 10);

	for (int x = 0; x < 10; x++)
	{
		pArray[x] = malloc(4);   // 动态开辟整数空间
		*(pArray[x]) = x;        // 动态赋值
	}

	PrintArray(pArray);

	// 释放堆内存
	for (int x = 0; x < 10; x++)
	{
		if (pArray[x] != NULL)
		{
			free(pArray[x]);  // 释放小的空间
			pArray[x] = NULL;
		}

		free(*pArray);   // 把最后的干了
		*pArray = NULL;
	}



	system("pause");
	return 0;
}
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char* argv[])
{
	char *p[] = { "package", "housing", "pace", "unleash" };


	char **cp = (char **)malloc(sizeof(char*)* 4);
	
	for (int x = 0; x < 4; x++)
	{
		cp[x] = (char*) malloc(10 * sizeof(char));
		sprintf(cp[x], "%s", p[x]);
	}

	for (int x = 0; x < 4; x++)
	{
		printf("输出堆数据: %s \n", *cp);
		cp++;
	}


	system("pause");
	return 0;
}

文件读取 新建一个文本,里面有几行数据,我们根据数组中的行数动态开辟内存空间,并且字符串长度是多长就分配多长的空间。

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

// 获取文件的总行数
int GetFileLine(FILE *fp)
{
	if (fp == NULL) return -1;

	char buf[1024] = { 0 };
	int line = 0;
	while (fgets(buf,1024,fp) != NULL)
	{
		++line;
	}
	// 恢复指针起始位置
	fseek(fp,0,SEEK_SET);
	return line;
}

int ReadFileData(FILE *fp,int line,char **pContent)
{
	char buf[1024] = { 0 };
	int index = 0;
	
	while (fgets(buf, 1024, fp) != NULL)
	{
		int curLineLen = strlen(buf) + 1;    // 获取每行数据长度
		//printf("读取到每行数据: %s", buf);
		// 给当前行分配内存
		char * lineContent = malloc(sizeof(char)* curLineLen);

		strcpy(lineContent, buf);
		pContent[index++] == lineContent;

		memset(buf, 0, 1024);
	}
}

void ShowFileContent(char **pContent, int line)
{
	for (int i = 0; i < line; i++)
	{
		printf("%d %s", i, pContent[i]);
	}
}

int main(int argc, char* argv[])
{

	FILE *fp = fopen("c:/Recovery.txt", "r");
	int line = GetFileLine(fp);
	// 分配的行数取决于文件行数
	char **pContent = malloc(sizeof(char*)* line);

	// 读取文件内容
	ReadFileData(fp, line, pContent);

	// 输出文件内容
	ShowFileContent(pContent, line);

	system("pause");
	return 0;
}

普通数组

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

void PrintArray(int *Array, int len)
{
	for (int x = 0; x < 10; x++)
	{
		printf("%d \n", Array[x]);
		printf("%d \n", *(Array + x));
	}
}

int main(int argc, char* argv[])
{
	int Array[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

	// PrintArray(Array, 10);

	system("pause");
	return 0;
}

指针运算

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

int main(int argc, char* argv[])
{

	int Array[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

	int *ptr = Array;

	ptr = &Array[10];

	int len = ptr - Array;

	printf("%d", len);

	system("pause");
	return 0;
}

定义指向数组的指针

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

int main(int argc, char* argv[])
{
	// 数组指针类型
	typedef int (Array_Type)[10];

	Array_Type MyArray;  // => int myarray[10];
	for (int x = 0; x < 10; x++)
	{
		MyArray[x] = x;
		// printf("%d ", MyArray[x]);
	}
	// 定义数组指针,指向整个数组的指针
	Array_Type *pArray = &MyArray;

	// pArray 指向了整个数组,如何遍历 ?
	for (int x = 0; x < 10; x++)
	{
		int num = *(*pArray + x);
		printf(" -> %d ", num);
	}


	// 2.直接定义数组指针类型,并指向数组
	int Array[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

	typedef int(*Array_Point)[5];       // 直接定义指针类型
	Array_Point pArray_Point = &Array;


	// 3.直接定义数组指针变量
	int(*pArray_Param)[10] = &Array;
	for (int x = 0; x < 10; x++)
	{
		printf("%d ", *(*pArray_Param + x));
	}

	system("pause");
	return 0;
}

多维指针定义数组:

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

void PrintArray(int(*Array)[3],int row,int col)
{
	for (int x = 0; x < row; ++x)
	{
		for (int y = 0; y < col; ++y)
		{
			// printf("%d ", *(*(Array + x) + y));
			printf("%d ", Array[x][y]);
		}
	}
}

int main(int argc, char* argv[])
{
	int Array[2][3] =  {{ 1, 2, 3 },{ 4, 5, 6 }};

	int(*pArray) = Array;
	//printf("%d ", (*pArray + 0)) => 1;
	//printf("%d ", (*pArray + 1) + 2 ) => 4;

	for (int x = 0; x < 3; x++)
	{
		printf("%d", ((*pArray + x) + 3));
	}

	PrintArray(Array,2,3);

	system("pause");
	return 0;
}

指针选择排序:

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

void PrintArray(char **Array,int len)
{
	for (int x = 0; x < len; ++x)
		printf("%s \n", Array[x]);
}

void SelectSort(char **Array, int len)
{
	for (int x = 0; x < len; ++x)
	{
		int min = x;
		for (int y = x + 1; y < len; ++y)
		{
			if (strcmp(Array[y], Array[min]) < 0)
				min = y;
		}

		if (min != x)
		{
			char *tmp = Array[min];
			Array[min] = Array[x];
			Array[x] = tmp;
		}
	}
}

int main(int argc, char* argv[])
{
	char *pArray[] = { "ddd", "bbb","sss", "qqq", "yyy", "eee", "ooo" };

	int len = sizeof(pArray) / sizeof(char *);
	SelectSort(pArray, len);

	PrintArray(pArray, len);

	system("pause");
	return 0;
}

void 万能指针

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

int main(int argc, char* argv[])
{
	// 万能指针,必须经过转换才可使用
	int number = 10;
	void *int_ptr = &number;  // 万能指针
	*(int *)int_ptr = 100;    // 赋值必须进行强转(告诉他需要读取多大的字节)
	printf("number => %d Address: %x \n", number,int_ptr);

	// --------------------------------------------------------------------
	// 针对数组类型的万能指针

	int Array[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	void *array_ptr = Array;     // 赋值一个空指针

	*(int *)array_ptr = 100;           // 改变第一个值
	*((int *)array_ptr + 1) = 200;     // 改变第二个值

	for (int x = 0; x < 10; x++)
		printf("%d ", Array[x]);

	system("pause");
	return 0;
}

指针数组排序:

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

void Bubble(int *Array, int len)
{
	for (int x = 0; x < len - 1; x++)
	{
		for (int y = 0; y < len - 1 - x; y++)
		{
			if (*(Array + y) > *(Array + y + 1))
			{
				int tmp = *(Array + y);
				*(Array+y) = *(Array + y + 1);
				*(Array + y + 1) = tmp;
			}
		}
	}

}

int main(int argc, char* argv[])
{
	int Array[10] = { 4,7,8,2,1,8,9,3,4,10 };
	int len = sizeof(Array) / sizeof(Array[0]);
	int *ptr = Array;

	Bubble(ptr, len);

	for (int x = 0; x < 10; x++)
	{
		printf("%d ", *(ptr+x));
	}

	system("pause");
	return 0;
}

野指针

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

int main(int argc, char* argv[])
{
	int a = 100;

	int *p = &a;

	p = 0xffff;

	*p = 200;

	system("pause");
	return 0;
}

指向函数的指针(函数指针):

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

int MyPrintA(int x,int y)
{
	printf("MyPrintA --> %d --> %d \n", x, y);
	return 1;
}

int main(int argc, char* argv[])
{
	printf("函数名入口: %d \n", &MyPrintA);

	// 直接定义并调用函数指针
	int *FuncAddr = (int *) &MyPrintA;    // 获取函数地址
	int(*MyFunc)(int,int) = FuncAddr;     // 定义函数指针
	int result = MyFunc(10,20);           // 调用函数指针

	// 定义函数类型,并通过类型定义函数指针
	typedef int(Func_Type)(int, int);     // 先定义类型
	Func_Type *pFunc = MyFunc;            // 定义函数指针
	pFunc(100, 200);                      // 调用(1)
	(*pFunc)(1000, 2000);                 // 调用(2)

	// 直接定义函数类型,并使用(1)
	typedef int(*Func_Ptr)(int, int);
	Func_Ptr pFunc2 = MyFunc;
	pFunc2(10000, 20000);
	// 直接定义函数类型,并使用(2)
	int(*pfunc)(int, int) = NULL;
	pfunc = MyFunc;
	pfunc(100000, 200000);

	// 如果拿到了一个地址,我们该如何将其转换为函数指针,并调用?
	// 此处应该关闭基址随机化 ASLR
	printf("函数名入口: %x \n", &MyPrintA);
	// (int (*)(int, int)) 0x4110e6;
	int(*Print)(int, int) = 0x4110e6;    // 转换为函数指针 MyPrintA
	Print(1, 2);                         // 直接调用

	system("pause");
	return 0;
}

函数指针实现动态参数调用

#include <stdio.h>

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

int Func2(int x, int y)
{
	return x - y;
}

void MyPrintA()
{
	// 只需要让指针指向不同的函数,就可以完成多态调用.
	int(*pFunc)(int, int) = Func1;   // 此处可以动态修改
	int ret = pFunc(1, 2);
	printf("Func1 = > %d \n", ret);
}

普通的函数指针参数传递: 实现了动态的参数传递,与函数传递,函数定制功能

#include <stdio.h>

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

int Func2(int x, int y)
{
	return x - y;
}
// 函数可以作为另外一个函数的参数
void doLogic(int(*pFunc)(int, int))
{
	int x = 10, y = 5;

	int ret = pFunc(x, y);
	printf("doLogic --> %d \n", ret);
}

int main(int argc, char* argv[])
{
	doLogic(Func2);

	system("pause");
	return 0;
}

函数指针数组 使用函数指针数组,实现一批相同调用规则的函数进行运算。

#include <stdio.h>

int add(int x, int y)
{
	int result = x + y;
	printf("x + y => %d ", result);
	return result;
}

int sub(int x, int y)
{
	int result = x - y;
	printf("x - y => %d ", result);
	return result;
}

int mul(int x, int y)
{
	int result = x * y;
	printf("x * y => %d ", result);
	return result;
}

int main(int argc, char* argv[])
{
	int(*func_array[3])(int,int);   // 定义函数指针数组

	func_array[0] = add;    // 分别给与不同的函数地址
	func_array[1] = sub;
	func_array[2] = mul;

	for (int x = 0; x < 3; x++)
	{
		int z = func_array[x](100,20);
		printf(" -> %d \n", z);
	}
	
	system("pause");
	return 0;
}

函数指针做函数参数,回调函数

#include <stdio.h>

// 输出数组中的数据。
void Print_Array(void *Array, int eleSize, int len, void(*print)(void *))
{
	char *start = (char *)Array;
	for (int x = 0; x < len; ++x)
	{
		//printf("数据: %d \n", start + x * eleSize);
		print(start + x * eleSize);
	}
}

// 这是回调函数
void MyPrint(void *recv)
{
	int *ptr = (int*)recv;
	printf("回调函数 --> 输出地址: %x --> 数据: %d \n", ptr,*ptr);
}

void MyPrintPerson(void *recv)
{
	struct Person *stu = (struct Person *)recv;
	printf("回调函数 --> 输出地址: %x \n", stu);
}

int main(int argc, char* argv[])
{
	int arry[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	Print_Array(arry, sizeof(int), 10, MyPrint);
// --------------------------------------------------------------------
	struct Person
	{
		char name[64];
		int age;
	};

	struct Person stu[] = { { "admin", 22 }, { "root", 33 } };
	Print_Array(stu, sizeof(struct Person), 2, MyPrintPerson);

	system("pause");
	return 0;
}