当前位置: 首页 > news >正文

嵌入式学习C语言(十五)指针函数 动态内存分配 函数指针 指针数组 指针指针

目录

一、指针函数

二、动态内存分配

        malloc函数

        free函数

         realloc函数

        calloc函数

        reallocarray函数

三、函数指针

        qsort函数 

四、指针数组

五、指针的指针

六、两句话技巧


一、指针函数

        1.返回值为指针的函数,不能返回局部变量的地址,全局变量、静态变量与传进去的指针地址均可返。

二、动态内存分配

        malloc函数

        1.  void *malloc(size_t  size);

        2.size_t  <==>  unsigned long  ,size 表示申请的空间的大小,单位字节。

        3.返回值:成功返回申请到内存空间的地址;失败返回 NULL。

        4.#include<stdlib.h>

        5.去堆上申请一段连续的空间。返回的是一个指针,指向申请的内存空间(内存空间未初始化全是随机数)。

        6.使用该函数后要判断内存空间是否申请到,申请空间申请不到会返回空指针。

        7.用完要释放空间。

        free函数

        1.  void free(void *ptr);

        2.释放之前申请的堆上的空间 。

        3.ptr 一定是之前申请到堆上空间的地址 。

eg   拼接字符串:先申请一个内存空间存放“Hello”字符串,再申请一个内存空间把“Hello”先放进去再把字符串“World!”拼接在后面,释放掉第一次申请的内存空间,输出拼接的字符串后释放掉第二次申请的内存空间。

int main(void){const char *s ={"Hello"};const char  *t ={"World"};char * p= malloc(strlen(s) + 1);    //因为隐含'\0'if(p != NULL)                                  //说明空间申请成功{strcpy(p,s);                             //字符串拷入堆中。char *q = malloc(strlen(q) + strlen(t) +1); //重新申请空间,使大小够装下新的 strcpy(q,p);                              strcat(q,t) ;  //进行拼接free(p);      //释放p指向的堆空间,p变成野指针p = q;         // 不让p变成野指针puts(q);     //打印字符串}free(q);   //释放p和q指向的堆空间return 0;}

         realloc函数

        1.void *realloc(void *ptr,size_t size);                

        2.void *ptr是原来空间的地址;size_t size是新开多大的空间;

        3.把原来空间的内容拷过来并释放原来的空间,可扩大可缩小。

eg   

int main(void)
{const char *s = "Hello";const char *t = "World!";char *p = malloc(strlen(s) + 1);if(p != NULL){strcpy(p, s);puts(p);p = realloc(p, strlen(p) + strlen(t) + 1);strcat(p, t);puts(p);}free(p);return 0;
}

        calloc函数

        1.void *calloc(size_t   nmemb, size_t  size);

        2.申请空间numemb * size 个字节,分几块,每块几个字节。

        reallocarray函数

        1.一般形式:void *reallocarray(void *ptr, size_t nmemb, size_t size);

三、函数指针

        1.指向函数类型的指针,指向一类函数。 int (*p) (int , int);

        2.函数的函数名  函数的第一条语句  均为函数的入口地址

        3.函数指针的形式要与回调函数的形式相同,参数可以只写个类型。

int  add(int a,int b)

{

        return a + b;

}

int sub(int a,int b)

{

        return a - b;

}

int main(void)

{

        int a = 10;

        int b = 20;

        int(*p)(int a,int b) ; //  函数指针,未赋值的野指针

        p = add;           // 将add函数的入口地址赋值给p

        p(a,b);               //间接调用函数

        (*p)(a,b);           //两种写法都可调用函数

        return 0;

}

        4.回调函数 

        通过函数指针在函数的参数中调用函数,将一个函数作为参数传递给另一个函数,当特定事件发生或条件满足时,接收参数的函数会调用这个传入的函数

int pow2(int n)   //返回该数的平方

{

        return n * n;

int fn(int n)   //返回该数本身

{

        return n;

}

void sort(int *a,int len,int(*pfn)(int))     //第三个参数用来说明,你要比较  数的平方  还是其本身

{                                                           //  甚至可以继续扩展,只要函数返回值为int型,且形参

        int i,j;                                            // 只有 一个int型

        for(i = 0;i < len - 1;++i)

        {

                for(j = i + 1;j < len;++j)

                {

                        if(pfn(a[i]) > pfn(a[j]))  //调用的函数比较

                        {

                                int t = a[i];

                                a[i] = a[j];

                                a[j]  = t;

                        }

                }

        }

}   //这是一个选择排序函数

int main(void)

{

        int a[] = {8,9,-5,1,4,3,2};

        int len =sizeof(a);

        sort(a,len,pow2);  //根据需求按他的平方大小排序。

        return 0;

}

        qsort函数 

        1.void qsort(void *base, size_t nmemb, size_t size,
                  int (*compar)(const void *, const void *));

        2. int (*compar)(const void *, const void *))是一个函数指针。

eg    调用qsort函数

int doublecmp(const void *p1, const void *p2)
{double *q1 = (double *)p1;double *q2 = (double *)p2;if(*q1 > *q2){return 1;}else if(*q1 == *q2){return 0;}else{return -1;}
}
int main()
{double a[] ={1,2,3,4,5,6,7,8,9,0};int len = sizeof (a) /sizeof(*a);qsort(a,sizeof(a) / sizeof(*a) , sizeof(*a),doublecmp);int i;for (i=0; i< len ; ++i){printf("lf\n",a[i]);}
}

eg 立即跳转到0x30001000地址处

void (*pfn)(void)
pfn = (void (*)(void)) 0x30001000 ;
pfn();

四、指针数组

        1.int  *a[10];   定义了一个数组,有10个指针(共占80个字节)

  eg1    打印字符串

void printfStrings(char *s[], int len)
{int i;for (i= 0;i < len; ++i){puts(s[i]);}
}
int main()
{char *s[3] ={"Hello","World","China"};     //s[0]存着"Hello"的地址,类推int len = sizeof(s) / sizeof (*s);printfStrings(s,len);return 0;
}

 eg2   找最大值

char *maxOfStrings(char *s[], int len)
{char *max;max = s[0];int i;for(i = 1;i < len;++i){if(strcmp(max, s[i]) < 0){max = s[i];}}return max;
}

五、指针的指针

        1.指向指针的指针。

void getMemory(char *p)
{p = malloc(100);
}
int main(void)
{char *s;getMemory(s);//s指针未指向malloc申请的100个字节strcpy(s, "Hello");//此行代码崩溃,s为野指针(随机数)puts(s);
}
void getMemory(char **p)//  char * 是p的基类型,后边一个*是类型说明符。指向指针的指针
{p = malloc(100);
}
int main(void)
{char *s;getMemory(&s);strcpy(s, "Hello");puts(s);
}

 eg1  找最大值

char *maxOfStrings(char **s, int len)
{char *max;max = s[0];int i;for(i = 1;i < len;++i){if(strcmp(max, *(s+i)) < 0){max = s[i];}}return max;
}
int main()
{char *s[] ={"Hello","World","China"};int len = sizeof (s) / sizeof (*s);puts(maxOfStrings(s,len));return 0;
}

eg 2  遍历数组

void printStrings(char **s, int len)
{int i;for(i = 0;i < len;++i){puts(*(s + i));}
}

eg3  逆序数组

void swap(char **a, char **b)
{char *t;t = *a;*a = *b;*b = t;
}void reverseStrings(char **s, int len)
{int i;for(i = 0;i < len / 2;++i){swap(s + i, s + len - i - 1);}
}

 eg4  字符串选择排序

void sortStrings(char **s, int len)
{int i, j;for(i = 0;i < len - 1;++i){for(j = i + 1;j < len;++j){if(strcmp(s[i], s[j]) > 0){swap(s + i, s + j);}}}
}

eg5    字符串二分查找

int binaryFindString(char **s, int len, const char *t)
{int begin = 0;int end = len - 1;int mid;while(begin <= end){mid = (begin + end) / 2;int ret = strcmp(s[mid], t);if(ret < 0){begin = mid + 1;}else if(ret > 0){end = mid - 1;}else{return mid;}}return -1;
}

六、两句话技巧

1.二维数组作为函数参数,形参为指向数组的指针;

2.指针数组作为函数参数,形参为指向指针的指针。

eg1   

void foo(int (*p)[4,int rows])

int  a[3][4];

int rows = sizeof(a) / sizeof(*a);

foo(&a[0], rows);

eg  2

void bar(char **s,len)

char *s[3];

int len = sizeof(s) /sizeof(*s);

bar(&s[0], len);

http://www.dtcms.com/a/274270.html

相关文章:

  • 变频器实习DAY5
  • 【硬核】6节串联锂电池均衡系统仿真_组内双向cuk均衡_组间双向反激式变压器
  • Linux 2.4 进程调度机制深度解析
  • Day32 Java方法03 方法的重载
  • 【Centos】Redis Cluster 集群部署图文步骤
  • 如何选择数据可视化工具?从设计效率到图表表现力全解读
  • 【AI学习】大模型微调实践
  • 策略模式实现
  • PyTorch 与 Spring AI 集成实战
  • Matlab裁剪降水数据:1km掩膜制作实战
  • JavaAI时代:重塑企业级智能开发新范式
  • OpenCV 与深度学习:从图像分类到目标检测技术
  • 端口到底是个什么鬼?回答我!
  • 虚幻引擎5 GAS开发俯视角RPG游戏 #06-2:优化EffectActor类
  • 鸿蒙开发之ArkTS数组
  • 深度体验飞算JavaAI:一场Java开发效率的革命
  • HarmonyOS NEXT端云一体化开发初体验
  • IPA软件源预览系统源码(源码下载)
  • 【跟着PMP学习项目管理】项目管理 之 采购管理知识点
  • Axios之核心语法详解
  • 上位机知识篇---常见的文件系统
  • 用数学构建权限系统:从集合论到位运算的高效设计
  • 前端开发—全栈开发
  • 主从服务器完整使用指南
  • 4万亿英伟达,凭什么?
  • SM712.TCT Semtech TVS二极管——电子设备的终极电路守护
  • 和鲸社区深度学习基础训练营2025年关卡2(1)纯numpy
  • 小皮面板搭建pikachu
  • 在 Linux 中配置天气机器人脚本开机自启动的完整指南
  • T16IZ遥控器教程__遥控器与无人机对频