news 2026/5/15 17:17:28

C语言(12) 函数指针,指针函数

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C语言(12) 函数指针,指针函数

字符指针常见错误

#include <stdio.h> int main(int argc, char **argv) { //char *p = "hello"; // hello 在内存中,只用一份,只能读取,不能修改 char p[] = "hello"; // char [] 开辟空间,会把hello字符串常量复制一份,给数组。 printf("%s\n", p); *(p + 0) = 'e'; // 如果是指针,操作是错误,不能修改常量 p[0] = 'e'; // 如果是数组,操作是对的,修改的是,数组里的内容,不是字符串常量 printf("%s\n", p); return 0; }

野指针

#include <stdio.h> void swap(int *a,int *b) { int *t; // int t; *t= *a; // t = *a; // *t ,是野指针 *a = *b; *b = *t; } int main(int argc, char **argv) { int a =10; int b =20; swap(&a,&b); /* */ return 0; }

函数指针,指针函数

1. 指针函数,函数的返回值是 指针类型 。

char *strcpy(char *dest, const char *src);
strcpy 这个函数的返回值,就是一个指针。 成功,指针指向 dest。

1), 不能返回,是局部作用域的指针。
2) ,希望函数,可以连续调用。 在同一个语句里面。 strcpy(str1,strcpy(str3,str2));
3)希望返回一端内存区域 (数组,堆空间)。

#include <stdio.h> #if 0 int * func1() // 错的 { int a[10]={1,2,3,4,5,6};// 0x2000 这个数组是个局部变量 printf("a addr %p\n",&a[0]); return a;// a == &a[0] ,不要返回局部变量 } int * func2() //对的 { static int a[10]={1,2,3,4,5,6};// 0x2000 printf("a addr %p\n",&a[0]); return a;// a == &a[0] } int main(int argc, char **argv) { int *p =NULL; p = func2(); printf("main p addr %p\n",p); printf("p[0] %d\n",p[0]); return 0; } //............................. int * fun3(int *a,int size) { a[1]=a[3]=a[5]=20; return a; } int main(int argc, char **argv) { int a[10]={0};// 0x2000 int * p = fun3(a,10); printf(" a[1]:%d a[3]:%d\n",a[1],a[3]); printf(" p[1]:%d p[3]:%d\n",p[1],p[3]); return 0; }
#include <stdio.h> #include <string.h> int mystrcpy(char *dst, char *src) { while (*src) { *dst = *src; dst++; src++; } *dst='\0'; return 0; } char* mystrcpy2(char *dst, char *src) { char * tmp = dst; while (*src) { *dst = *src; dst++; src++; } *dst='\0'; return tmp; } char* mystrcat(char *dst,char * src) { char* tmp = dst; while(*dst) { dst++; } while(*src) { *dst=*src; src++; dst++; } *dst ='\0'; return tmp; } int main(int argc, char **argv) { char str1[100]="hello"; char str2[100]="ok"; char str3[100]={0}; // char *strcpy(char *dest, const char *src); //strcpy(str1,strcpy(str3,str2));// strcpy(str3,str2);== str3 , strcpy(str1,str3); //printf("str1 is %s\n",str1); // mystrcpy2(str1,mystrcpy2(str3, str2)); // printf("str1 is %s\n",str1); mystrcat(str3,mystrcat(str1,str2)); printf("str3 is %s\n",str3); return 0; }

2. 函数指针

前面介绍的指针,基本都是指数据。

函数指针:指向一个函数。本质,指针变量;

函数名,是地址值。里面储存的代码,对数据进行加减乘除操作的。

目的

避免代码的重复。 方便后期代码的扩展。函数功能的解耦合。

回调函数

一个函数被当作参数 ,传递给另外一个函数。 被传递这个参数(函数指针,回调函
数);被动调用。主调函数只是传参(函数)

语法 int add(int a, int b) // int (*) (int,int) { return a + b; } int main(int argc, char **argv) { int (*p)(int, int) =add; // p 函数指针。 add 不能写成add(), 不是对add函数的调用 int a = 10; int b = 20; int ret = 0; ret = add(a, b); printf("add() is %d\n", ret); ret = p(a, b); // 通过函数指针 对函数的调用 printf("p() is %d\n", ret); return 0; }
#include <stdio.h> #include <stdlib.h> #include <time.h> int fill_array(int *a, int size) { int i = 0; // for(i=0;i<size;i++) // { // a[i] = rand()%50; // } for (i = 0; i < size; i++) { //(*a)+i = rand()%50; *(a + i) = rand() % 50; } return 0; } int find_num3(int* a,int size) { for(size_t i=0;i<size;i++) { if(0 == a[i]%3) { printf("%d\n",a[i]); } } return 0; } int find_num5(int* a,int size) // int (*) (int*,int) { // int a; int ; int* p ;int* for(size_t i=0;i<size;i++) { if(0 == a[i]%5) { printf("%d\n",a[i]); } } return 0; } //............................................... int div3(int num) // div3 -> int (*) (int) { return 0 == num %3; } int div5(int num) // div3 -> int (*) (int) { return 0 == num %5; } void find_num(int* a,int size, int (*fun) (int) ) { for(size_t i=0;i<size;i++) { if( fun(a[i])) // if( div5(a[i])) { printf("%d\n",a[i]); } } } int main(int argc, char **argv) { srand(time(NULL)); int a[10]={0}; fill_array(a,10); //find_num3(a,10); find_num(a,10,div5); // div5(); return 0; }

typedef 关键字

取别名, 给数据类型取别名

1. 普通数据类型 去别名

typedef 老数据类型名 新数据类型名 typedef unsigned char u8; typedef unsigned short u16; typedef char s8; int main(int argc, char **argv) { u8 a; // unsigned char u16 b; // unsigned short s8 c; // char return 0; }

2. 简化函数指针的写法

typedef int* (*PFUN)(int ,int ,char* ); // int* func(int a,int b ,char* c) // int* (*)(int ,int ,char* ) // { // return NULL; // } // int func2(int a,int b, int* (*pfun)(int ,int ,char* )) // { // return 0; // } int* func(int a,int b ,char* c) // int* (*)(int ,int ,char* ) { return NULL; } int func2(int a,int b, PFUN pfun) { char str[]={0}; pfun(1,2,str); return 0; }

3.和结构体有关,晚些介绍

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/15 17:16:31

3步诊断法:用Obsidian导入工具解决笔记迁移难题

3步诊断法&#xff1a;用Obsidian导入工具解决笔记迁移难题 【免费下载链接】obsidian-importer Obsidian Importer lets you import notes from other apps and file formats into your Obsidian vault. 项目地址: https://gitcode.com/gh_mirrors/ob/obsidian-importer …

作者头像 李华
网站建设 2026/5/15 17:14:05

HTML转Figma:连接网页开发与设计协作的桥梁

HTML转Figma&#xff1a;连接网页开发与设计协作的桥梁 【免费下载链接】figma-html Convert any website to editable Figma designs 项目地址: https://gitcode.com/gh_mirrors/fi/figma-html 在今天的数字产品开发流程中&#xff0c;设计和开发团队之间的协作常常面临…

作者头像 李华
网站建设 2026/5/15 17:13:09

Java---包装类与泛型

1.包装类1.1 包装类在Java中&#xff0c;由于基本数据类型不是继承Object类&#xff0c;为了在泛型代码中可以支持基本数据类型&#xff0c;Java给每个基本数据类型各自提供了一个包装类。如下图除了char和int基本数据类型的包装类型有点特别&#xff0c;其他的都是首字母大写 …

作者头像 李华
网站建设 2026/5/15 17:13:09

企业级漏洞管理:5个cve-search高级搜索策略提升安全团队效率

企业级漏洞管理&#xff1a;5个cve-search高级搜索策略提升安全团队效率 【免费下载链接】cve-search cve-search - a tool to perform local searches for known vulnerabilities 项目地址: https://gitcode.com/gh_mirrors/cv/cve-search cve-search是一款强大的本地漏…

作者头像 李华
网站建设 2026/5/15 17:09:13

GitHub Profile深度定制:从Markdown到Actions的自动化实践

1. 项目概述&#xff1a;一个GitHub Profile的深度定制实践如果你在GitHub上搜索过一些知名的开发者或组织&#xff0c;可能会发现他们的主页&#xff08;Profile&#xff09;与众不同——它不是一个简单的仓库列表&#xff0c;而是一个精心设计的、信息丰富的个人或团队门户。…

作者头像 李华