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

C语言函数指针和结构体

函数指针、数组、结构体

一、函数指针

1.1 函数名

  • 一个函数在编译时被分配一个入口地址,这个地址就称为函数的指针,函数名代表函数的入口地址
#include <stdio.h>// 定义一个简单的函数
void func(){printf("这是内部打印\n");
}int main() {// 打印函数func的地址,三种写法结果相同// func: 函数名本身就是函数的地址// &func: 取函数的地址// *func: 解引用函数指针,但仍然得到函数的地址printf("%p %p %p\n", func, &func, *func); // 这三种的取到的函数地址都是一样的// 函数指针的使用:函数的地址加()是调用函数func();       // 直接通过函数名调用(*func)();    // 通过解引用函数指针调用(&func)();    // 通过取函数地址并调用return 0;
}

1.2 函数指针

  • 函数指针:它是指针,指向函数的指针

  • 语法格式:

    返回值 (*函数指针变量)(形参列表);
    
    • 函数指针变量的定义,其中返回值、形参列表需要和指向的函数匹配
#include <stdio.h>// 定义一个简单的加法函数
int add(int a, int b) {return a + b;
}int main() {// 定义的同时赋值,初始化// 声明一个函数指针p1,它指向一个接受两个int参数并返回int的函数// 将add函数的地址赋给p1,这样p1就成为了add函数的别名int (*p1)(int, int) = add; // p1就是add的别名printf("%d\n", p1(1, 2)); // 通过函数指针调用add函数// 先定义后赋值// 声明一个函数指针p2,它指向一个接受两个int参数并返回int的函数int (*p2)(int, int);// 将add函数的地址赋给p2// p2 = &add; // 这种写法也是正确的,&add表示取add函数的地址p2 = add; // 函数名本身就是函数的地址,所以可以直接赋值printf("%d\n", p2(60, 50)); // 通过函数指针调用add函数return 0;
}

1.3 回调函数

  • 函数指针变量做函数参数,这个函数指针变量指向的函数就是回调函数
  • 回调函数可以增加函数的通用性:在不改变原函数的前提下,增加新功能
#include <stdio.h>// 定义一个简单的加法函数
int add(int a, int b) {return a + b;
}
// 定义一个简单的减法函数
int sub(int a, int b) {return a - b;
}
// 定义一个回调函数,接受两个整数和一个函数指针作为参数
// 函数指针p指向一个接受两个int参数并返回int的函数
int cocl(int x, int y, int (*p)(int, int)) {// 通过函数指针调用相应的函数int temp = p(x, y);return temp;
}
int main() {// 这是加法// 调用cocl函数,传入10和20以及add函数的地址int temp = cocl(10, 20, add);printf("%d\n", temp); // 输出加法结果// 调用减法// 调用cocl函数,传入10和20以及sub函数的地址int temp2 = cocl(10, 20, sub);printf("%d\n", temp2); // 输出减法结果return 0;
}

三、结构体

3.1 结构体的使用

#include <stdio.h>// 定义一个结构体Student,包含姓名、年龄和性别
struct Student {char name[20]; // 姓名int age;       // 年龄char sex;      // 性别
};int main() {// 定义一个Student结构体变量s并初始化struct Student s = {"feifei", 19, 'm'};// 通过普通变量访问结构体成员,使用.操作符printf("%s %d %c\n", s.name, s.age, s.sex);// 定义一个指向Student结构体的指针pstruct Student *p;// 将s的地址赋给指针pp = &s;// 通过指针访问结构体成员,使用->操作符printf("%s %d %c\n", p->name, p->age, p->sex);return 0;
}

3.2 结构体值传参

  • 传值是指将参数的值拷贝一份传递给函数,函数内部对该参数的修改不会影响到原来的变量
#include <stdio.h>
#include <string.h> // 添加string.h头文件以使用strcpy函数// 定义一个结构体Student,包含姓名、年龄和性别
struct Student {char name[20]; // 姓名int age;       // 年龄char sex;      // 性别
};// 值传递:将结构体变量s的副本传递给函数
// 在函数内部对s的修改不会影响到main函数中的s
void f1(struct Student s) {strcpy(s.name, "zhansan"); // 修改姓名s.age = 18;                // 修改年龄s.sex = 'm';               // 修改性别printf("函数体中修改:%s %d %c\n", s.name, s.age, s.sex);
}// 指针传递:将结构体变量s的地址传递给函数
// 在函数内部通过指针修改s的内容会直接影响到main函数中的s
void f2(struct Student *p) {strcpy(p->name, "mafeifei"); // 通过指针修改姓名p->age = 18;                 // 通过指针修改年龄p->sex = 'm';                // 通过指针修改性别printf("f2函数体中修改:%s %d %c\n", p->name, p->age, p->sex);
}int main() {// 定义一个Student结构体变量s并初始化struct Student s = {"feifei", 19, 'm'};// 通过普通变量访问结构体成员,使用.操作符// f1(s); // 值传递,不会修改main函数中的s// 通过指针传递,会修改main函数中的sf2(&s); // 传递s的地址printf("函数体执行后:%s %d %c\n", s.name, s.age, s.sex);return 0;
}

3.3 结构体地址传递

  • 传址是指将参数的地址传递给函数,函数内部可以通过该地址来访问原变量,并对其进行修改。
#include <stdio.h>
#include <string.h>// 定义一个结构体Student,包含姓名、年龄和性别
struct Student {char name[20]; // 姓名int age;       // 年龄char sex;      // 性别
};// 通过地址传递修改结构体成员
void updateStudent(struct Student *s) {strcpy(s->name, "张三"); // 修改姓名s->age = 20;            // 修改年龄s->sex = 'M';           // 修改性别
}// 打印结构体成员
void printStudent(struct Student s) {printf("姓名: %s, 年龄: %d, 性别: %c\n", s.name, s.age, s.sex);
}int main() {// 定义一个Student结构体变量并初始化struct Student student = {"李四", 18, 'F'};printf("修改前:\n");printStudent(student);// 通过地址传递修改结构体成员updateStudent(&student);printf("修改后:\n");printStudent(student);return 0;
}
http://www.dtcms.com/a/310823.html

相关文章:

  • 第13届蓝桥杯Python青少组中/高级组选拔赛(STEMA)2022年1月22日真题
  • socket编程-UDP(2)-设计翻译系统
  • 基于线性规划的储能充放电仿真系统
  • 读取数据集及数据集划分
  • 7.苹果ios逆向-目录结构
  • 【vue】Vue 项目创建工具对比:vue create 与 create-vue 的核心区别
  • 安卓开发--LinearLayout(线性布局)
  • 华锐矩阵世界平台与海外客户洽谈合作
  • 将 YOLOv11 的 .pt 模型转换为 YOLOv8 格式需要特定的处理流程 机器学习 计算机视觉cv
  • Spotlight on MySQL 300安装教程(附使用指南):实时监控MySQL性能的工具
  • 好未来披露2026财年Q1财报:净利润3128万美元,同比大增174%
  • 解决IDEA中MAVEN项目总是将LANGUAGE LEVEL重置的问题
  • InteriorGS 数据集
  • 力扣-字母异位词
  • gpu 优化
  • 从删库到跑路?MyBatis3逻辑删除实战:优雅规避数据灾难
  • 一致连续性背后的直觉是什么?
  • 高速信号设计之 DDR5 篇
  • 【unity实战】简易的车辆控制系统
  • 从零开始:Kaggle 竞赛实战入门指南
  • 鸿蒙系统PC安装指南
  • 【RH124 问答题】第 9 章 控制服务和守护进程
  • 测试分类:详解各类测试方式与方法
  • 告别“AI味”图像!最新开源AI模型FLUX.1-Krea实现真实光影生成
  • 【n8n】如何跟着AI学习n8n【05】:Merge节点和子流程调用
  • Prim算法
  • 交叉编译简介
  • 【JAVA面试】基础篇
  • 广东省省考备考(第六十三天8.1)——资料分析、数量(强化训练)
  • 【AI应用】 能源保供战:AI大模型如何守护万家灯火?