指针数组:
#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 = #
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;
}