【C语言入门】自定义函数的模块化设计原则

c语言各章知识重点(谭浩强版本) 第一章 C语言概述 1、C程序的组成和形式的基本特点(P6-7) (1)C程序是由函数构成的,一个C源程序至少且仅包含一个main函数,也可以包含一个main函数和若干个其他函数。 (2)一个函数由两部分组成 函数的首部:即函数的第一行,包括函数名、函数类型、函数属性、函数参数名、参数类型 例:int max (int x, int y) 一个函数名后面必须跟一对圆括号,括号内写函数的参数名及其类型。函数可以没有参数,如main()。 函数体:即函数首部下面的花括号内的部分。如果一个... 阅读详情

第一章 模块化设计的本质与核心价值

1.1 从程序复杂度谈起

随着软件规模扩大,代码行数从几千跃升至百万级(如 Linux 内核超 2000 万行),单纯依靠顺序结构和分支循环会导致:

  • 认知过载:程序员难以同时处理数万行代码的逻辑关系
  • 维护成本爆炸:修改一处功能可能引发连锁反应
  • 复用效率低下:重复代码量超过 70%(据 Gartner 统计)

模块化设计通过 “分而治之” 将系统分解为可管理的单元,每个单元(函数)满足:

  • 信息隐藏:内部实现细节对外透明
  • 高内聚:函数功能高度集中
  • 低耦合:函数间依赖关系简单可控
1.2 函数作为模块化的基本载体

在 C 语言中,函数是天然的模块化单元,具备完整的封装边界:

// 典型函数结构
返回类型 函数名(参数列表) {
    局部变量定义;
    功能实现代码;
    return 返回值;
}

每个函数实现独立功能,通过参数传递(输入)和返回值(输出)与外界交互,形成 “黑箱” 模型。这种封装机制使得:

  • 调用者无需关心内部算法(如排序函数不必知道是冒泡还是快速排序)
  • 开发者可专注单个函数的逻辑正确性
  • 便于单元测试和错误定位
第二章 五大核心设计原则详解
2.1 单一职责原则(SRP, Single Responsibility Principle)

定义:每个函数应该仅有一个引起其变化的原因
示例:错误处理函数不应同时包含日志记录功能

// 反例:混合职责
void process_error(char* msg, int level) {
    // 错误处理逻辑
    if(level > 3) {
        // 同时包含日志写入
        FILE* f = fopen("error.log", "a");
        fprintf(f, "%s\n", msg);
        fclose(f);
    }
}

// 正例:拆分为独立函数
void handle_error(int level) { /* 错误处理 */ }
void log_error(char* msg) { /* 日志记录 */ }

违反后果:

  • 代码变更风险增加(修改日志格式可能破坏错误处理逻辑)
  • 功能复用困难(日志模块无法单独用于其他场景)
  • 测试复杂度上升(需同时验证两个不相关功能)

实现要点:

  1. 函数规模控制:理想代码行数 50-200 行(超过 300 行需警惕职责扩散)
  2. 功能边界清晰:用动词短语命名(如validate_input()而非process_data())
  3. 依赖分析:通过调用图工具检查函数是否承担多重职责
2.2 接口隔离原则(ISP, Interface Segregation Principle)

定义:函数接口应最小化,避免调用者依赖不需要的功能
示例:文件操作函数不应强制要求传入网络连接参数

// 反例:臃肿接口
int file_operation(char* path, int net_mode, ...); // net_mode对本地文件无意义

// 正例:细分接口
int local_file_open(char* path);
int network_file_open(char* path, int net_mode);

接口设计三要素:

  1. 参数类型:优先使用基本类型,复杂数据通过结构体封装
// 推荐做法
typedef struct {
    char* username;
    int age;
} UserInfo;
int process_user(UserInfo* info);

// 避免过多离散参数
int bad_process(char* username, int age, char* email, ...);

  1. 返回值设计:
    • 成功 / 失败场景用int(0 / 非 0)
    • 复杂结果用指针输出参数
    • 错误码使用枚举类型增强可读性
typedef enum {
    OK = 0,
    ERR_FILE_NOT_FOUND,
    ERR_PERMISSION_DENIED
} ErrorCode;
ErrorCode open_file(char* path, FILE** fp);

  1. 文档规范:使用 Doxygen 格式明确参数约束和返回语义
/**
 * @brief 计算圆面积
 * @param radius 圆半径,必须大于0
 * @return 圆面积,半径≤0时返回-0.0
 */
double calc_area(double radius);
2.3 高内聚原则(High Cohesion)

定义:函数内部元素对同一功能的支持程度
分为七类内聚类型(从低到高):

  1. 偶然内聚:代码无逻辑关联(如随机组合的错误处理)
  2. 逻辑内聚:处理相似功能(如同时处理多种文件类型)
  3. 时间内聚:按执行顺序组合(如初始化系列变量)
  4. 过程内聚:按算法步骤组合(如排序函数包含数据校验)
  5. 通信内聚:操作同一数据(如同时读写用户信息结构体)
  6. 顺序内聚:前一步输出为后一步输入(如数据解析 + 验证)
  7. 功能内聚:唯一功能目标(理想状态,如单纯的加密函数)

高内聚实现策略:

  • 数据集中处理:所有操作围绕同一组数据(如user.c中的函数均操作User结构体)
  • 算法单一化:避免在一个函数中混合多种实现逻辑
  • 去除冗余代码:通过抽取子函数实现代码重用
// 低内聚示例(混合文件操作和数据计算)
void process_data() {
    FILE* f = fopen("data.txt", "r");
    // 读取数据
    // 复杂计算逻辑
    fclose(f);
}

// 重构为高内聚
void read_data(FILE* f, Data* buf) { /* 专注读取 */ }
void compute_data(Data* buf) { /* 专注计算 */ }
2.4 低耦合原则(Low Coupling)

定义:函数间依赖关系的强弱程度
分为五类耦合类型(从高到低):

  1. 内容耦合:直接操作其他函数内部变量(严禁!)
// 反例:修改外部函数的局部变量
void funcA() { int x=0; }
void funcB() { x=1; } // 非法访问

  1. 公共耦合:共享全局变量(慎用!)
int global_var;
void funcA() { global_var++; }
void funcB() { global_var--; }

  1. 控制耦合:传递控制标志(需谨慎)
void process(int flag) {
    if(flag) { /* 分支逻辑 */ }
    else { /* 另一分支 */ }
}

  1. 印记耦合:传递复杂数据结构(推荐)
typedef struct { int a, b; } Data;
void process(Data* d) { /* 操作结构体 */ }

  1. 数据耦合:传递基本数据类型(理想状态)
int add(int a, int b) { return a+b; }

降低耦合实践:

  1. 减少全局变量使用:通过参数传递替代
  2. 依赖倒置原则:高层模块不依赖底层实现(通过函数指针实现)
// 高层模块
typedef int (*CompareFunc)(int, int);
void sort(int* arr, int len, CompareFunc cmp);

// 底层实现
int ascending(int a, int b) { return a - b; }
int descending(int a, int b) { return b - a; }

  1. 接口标准化:定义统一的数据交互格式(如结构体)
2.5 可复用原则(Reusability Principle)

定义:函数设计应考虑在不同场景的重复使用
可复用函数特征:

  • 无平台依赖代码(通过条件编译处理差异)
#ifdef WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif

  • 通用算法实现(如排序、查找函数不绑定特定数据类型)
  • 最小必要依赖(仅依赖标准库或公共模块)

泛型实现技巧:

  1. 使用void*指针实现通用数据操作
void swap(void* a, void* b, size_t size) {
    char tmp[size];
    memcpy(tmp, a, size);
    memcpy(a, b, size);
    memcpy(b, tmp, size);
}

  1. 宏定义实现类型无关
#define MAX(a, b) ((a) > (b) ? (a) : (b))

  1. 模板化设计(C11 _Generic 关键字)
_Generic(x,
    int: int_process,
    float: float_process,
    default: default_process
)(x);
第三章 模块化设计的实施路径
3.1 需求分析阶段:功能分解技术
  1. 层次分解法:从顶层功能逐层拆解
学生成绩管理系统
├─ 数据录入模块
│  ├─ 单个学生录入
│  └─ 批量文件导入
├─ 成绩计算模块
│  ├─ 平均分计算
│  └─ 排名生成
└─ 报表输出模块
   ├─ 控制台打印
   └─ PDF文件生成

  1. 数据流分析:通过输入输出确定函数边界
输入:学生信息表 → 处理函数:validate_info() → 输出:合法信息表

  1. 职责矩阵法:用 RACI 模型明确函数职责
    | 函数 | 需求分析 | 代码实现 | 测试 | 维护 |
    |-------------|----------|----------|------|------|
    | input_data | R | A | I | C |
    | calc_score | R | A | I | C |
3.2 设计阶段:结构化建模工具
  1. 流程图:展示函数内部执行逻辑(注意避免过度复杂)
  2. UML 类图:描述函数与数据结构的关系(C 语言中通过结构体模拟类)
  3. 调用关系图:使用 Graphviz 生成函数依赖图,检测循环依赖
digraph func_call {
    main -> input_data;
    main -> process_data;
    process_data -> validate_data;
    process_data -> compute_result;
}
3.3 编码阶段:规范与最佳实践
  1. 命名规范:

    • 驼峰命名法:calculateAverageScore()
    • 前缀标识:int_表示整数操作,str_表示字符串处理
    • 禁止使用单字母变量(除循环索引i,j,k)
  2. 参数顺序:

    • 输入参数在前,输出参数在后(带*指针)
    • 基本类型在前,结构体 / 指针在后
    int read_config(const char* path, Config* cfg); // 输入路径,输出配置
    
  3. 错误处理:

    • 每个函数入口检查参数合法性
      • 复杂错误通过全局错误码处理(如errno机制)
    void func(int* ptr) {
        if(ptr == NULL) {
            fprintf(stderr, "Null pointer error\n");
            exit(EXIT_FAILURE);
        }
        // 正常逻辑
    }
    
  4. 代码注释:

    • 函数级:说明功能、参数、返回值、异常处理
    • 关键逻辑:解释算法关键点(如快速排序的分区逻辑)
    • 禁止注释显而易见的代码(如i = i + 1; // 增加i)
第四章 典型案例分析:学生成绩管理系统
4.1 模块划分
// 数据结构定义(student.h)
typedef struct {
    char name[20];
    int age;
    float scores[3]; // 语数外成绩
} Student;

// 输入模块(input.c)
Student* input_student(); // 交互式录入单个学生
int input_batch_students(char* filename, Student** list); // 从文件批量导入

// 计算模块(calc.c)
float calc_average(Student* stu); // 计算单科平均分
void sort_students(Student* list, int num, int (*cmp)(Student*, Student*)); // 通用排序函数

// 输出模块(output.c)
void print_student(Student* stu); // 打印单个学生信息
void print_report(Student* list, int num); // 打印成绩报表
4.2 核心函数实现(sort_students)
// 比较函数示例:按总分降序
int compare_by_total(Student* a, Student* b) {
    float total_a = a->scores[0] + a->scores[1] + a->scores[2];
    float total_b = b->scores[0] + b->scores[1] + b->scores[2];
    return (total_b - total_a) > 0 ? 1 : -1;
}

// 排序函数实现(冒泡排序)
void sort_students(Student* list, int num, int (*cmp)(Student*, Student*)) {
    for(int i=0; i<num-1; i++) {
        for(int j=0; j<num-i-1; j++) {
            if(cmp(&list[j], &list[j+1]) < 0) { // 交换顺序
                Student tmp = list[j];
                list[j] = list[j+1];
                list[j+1] = tmp;
            }
        }
    }
}
4.3 模块间交互
// 主函数逻辑(main.c)
int main() {
    Student* students = NULL;
    int count = input_batch_students("scores.csv", &students); // 输入模块
    
    sort_students(students, count, compare_by_total); // 计算模块排序
    
    print_report(students, count); // 输出模块打印报表
    
    free(students); // 资源释放
    return 0;
}
4.4 模块化优势体现
  1. 开发效率:三人团队可同时开发 input/calc/output 模块
  2. 测试便捷:可单独测试sort_students函数,使用不同比较器
  3. 维护成本:修改打印格式只需更新print_report函数
  4. 复用潜力:sort_students可复用到员工绩效排序等场景
第五章 常见反模式与解决方案
5.1 反模式 1:巨型函数(God Function)

特征:代码超过 1000 行,包含多个不相关功能
危害:代码可读性为 0,调试如 “大海捞针”
重构方法:

  1. 识别功能边界:用空行分隔不同逻辑块
  2. 抽取子函数:将独立逻辑封装为新函数
  3. 数据封装:通过结构体传递相关数据
5.2 反模式 2:面条式调用(Spaghetti Call)

特征:函数间循环调用,依赖关系混乱

void A() { B(); }
void B() { C(); }
void C() { A(); } // 循环依赖

解决方案:

  1. 引入中间层:通过抽象接口打破循环
  2. 依赖反转:高层模块依赖抽象而非具体实现
  3. 使用全局数据池:通过共享数据结构减少直接调用
5.3 反模式 3:魔术值滥用(Magic Value)

特征:函数内部硬编码常数,如if(type == 123)
危害:代码可维护性差,修改一处需改多处
最佳实践:

  1. 使用#define定义常量
#define STUDENT_TYPE 123
if(type == STUDENT_TYPE) { ... }

  1. 枚举类型增强语义
typedef enum {
    TYPE_STUDENT = 123,
    TYPE_TEACHER = 456
} UserType;
if(type == TYPE_STUDENT) { ... }
第六章 未来发展与前沿实践
6.1 C11 新特性对模块化的增强
  1. _Generic 关键字:实现轻量级泛型编程
#define min(X, Y) _Generic((X), \
    int: int_min, \
    float: float_min, \
)(X, Y)

  1. 匿名结构体:简化局部数据封装
void func() {
    struct { int a; float b; } data = {.a=10, .b=3.14};
    // 使用data进行操作
}

  1. _Pragma 操作符:标准化编译指示
_Pragma("GCC optimize(\"O3\")") // 等价于#pragma GCC optimize("O3")
6.2 现代工具链支持
  1. 静态分析工具:
    • Clang-Tidy:检测低内聚、高耦合代码
    • PC-Lint:检查未使用的参数和未返回的分支
  2. 模块化测试框架:
    • Unity:轻量级 C 语言单元测试框架
    TEST(AddFunction, PositiveNumbers) {
        TEST_ASSERT_EQUAL_INT(5, add(2, 3));
    }
    
  3. 包管理工具:
    • Conan:管理 C 语言模块依赖
    • Premake:生成跨平台项目配置
结语:从代码匠到架构师的必经之路

模块化设计不仅是一种编程技巧,更是一种系统思维的体现。当你能熟练运用五大原则设计函数时,你会发现:

  • 复杂问题变得清晰可控
  • 代码不再是混乱的字符堆砌,而是层次分明的功能组件
  • 维护代码从噩梦变成有规律的 “模块替换” 游戏

记住:优秀的程序员不是写最长的代码,而是能把复杂逻辑拆分成最优雅的模块。从现在开始,每写一个函数都问自己三个问题:

  1. 它是否只做一件事?(单一职责)
  2. 接口是否足够简洁?(接口隔离)
  3. 未来能否重复使用?(可复用性)

形象化理解:把程序比作 “乐高积木工厂”

想象你要组装一个超大型乐高城堡,直接堆零件会乱成一团。聪明的做法是先分类:把所有城墙零件放一箱(专门拼城墙)、塔楼零件放一箱(专门拼塔楼)、装饰零件放一箱(专门拼细节)。每个箱子就像 C 语言里的 “自定义函数”,它们有三个关键特性:

1. 每个箱子只做一件事(单一职责原则)

比如 “计算城墙长度” 的箱子,绝对不插手 “给塔楼涂颜色” 的工作。就像你让妈妈帮忙拿零食,不会同时让她洗碗 —— 专注才能高效。如果一个函数既算成绩又打印报表,就像让一个人同时擦玻璃和拖地,容易出错还难改。

2. 箱子对外有 “使用说明书”(接口清晰)

你不用知道箱子里的零件怎么摆放,只要看说明书就知道:“输入城墙的块数,就能得到总长度”。这就是函数的 “参数” 和 “返回值”。比如你调用calc_wall_length(n),只要给n(积木块数),就能拿到结果,不用操心里面怎么计算每块积木的尺寸。

3. 箱子可以反复使用(可复用性)

拼完一个城堡的城墙,下次拼另一个城堡时,这个 “城墙箱子” 还能直接用。就像你写了一个计算圆面积的函数,算水杯底面积和锅盖面积时,直接调用就行,不用重复写公式3.14*r*r。这就像妈妈织毛衣的毛线团,织围巾和手套都能用,省时间又少出错。

简单总结:模块化设计就是把大程序拆成小函数,每个函数像 “功能盒子”,只做一件事,通过 “输入输出” 和外界打交道,还能重复用。就像用不同的乐高盒子拼出复杂城堡,用不同的函数拼出复杂程序,哪里坏了换哪个盒子,想加新功能就造新盒子,特别方便!

C语言基础教程(五):函数与模块化编程完全指南​ 函数是C语言程序的基本构建块,它将复杂的程序分解为更小、更易管理的功能单元。就像建筑使用标准构件一样,函数让程序变得模块化、可重用和易于维护。掌握函数的使用是成为合格程序员的关键一步。本文将全面解析C语言函数的各种特性和高级用法,帮助您构建结构良好的程序。 阅读详情

相关推荐

单片机C语言模块化编程实战指南

在软件工程中,模块化编程是一种设计范式,它将复杂系统分解为更小、更易管理的模块。每个模块拥有定义良好的接口和封装的内部实现,便于独立开发和维护。对于单片机编程而言,模块化尤其关键,因为单片机通常具有资源受限的特点,模块化有助于简化开发流程并优化资源使用。C语言是一种广泛使用的编程语言,具有强大的功能和灵活性,非常适合进行系统编程和嵌入式开发。它的语法结构包括了数据类型声明、变量定义、运算符、控制语句、函数定义等基本编程元素。例如,在定义一个变量时,需要指定数据类型,如int代表整数类型,

weixin_35950531的博客 1284

C语言基础 — ( 函数——模块化设计)

函数”是从英文 function 翻译过来的,其实,function在英文中的意思是“函数”,也是“功能”。从本质意义上来说,函数就是用来完成一定的功能的。这样,对函数的概念就很好理解了,所谓函数名就是给该功能起一个名字,如果该功能是用来实现求正弦运算的,就称为正弦函数。函数就是功能。每一个函数用来实现一个特定的功能。函数的名字应反映其代表的功能。在设计一个较大的程序时,往往把它分为若干个程序模块,每一个模块包括一个或多个函数,每个函数实现一个特定的功能。一个C程序可由一个主函数和若干个其他函数构成。

weixin_44759598的博客 2079

C语言函数大全及详解:从基础到高级实战指南

在现代C语言开发中,自定义函数不仅是代码复用的核心手段,更是构建可维护、可扩展系统架构的基石。随着项目规模的增长,良好的函数设计能力直接决定了软件系统的健壮性与团队协作效率。一个设计合理的函数应当具备清晰的责任边界、稳定的接口契约以及高效的执行路径。本章将深入探讨如何从模块化思想出发,结合工程实践,系统地完成自定义函数的设计与实现过程。通过分析高内聚低耦合原则、参数规划策略、返回值机制设计,并辅以数学运算工具库的完整案例,全面揭示高质量函数编码的技术要点和最佳实践。

weixin_42181686的博客 907

C语言---利用函数实现模块化程序设计

本章主要介绍函数模块化的使用,包括库函数、自定义函数的讲解,函数的定义、声明和调用以及相关函数调用的练习,函数的嵌套使用与递归使用,最后介绍了数组作为函数参数的使用。

m0_56399733的博客 2866

C高级编程 基于模块化设计思想的C语言开发

  C语言是一个“古老”的编程工具。在嵌入式系统、自控系统及计算机底层操作系统、数据处理中间件等系统开发中仍然是优先选择的开发工具。不同于很多更“高级”的编程语言,如Java,Python等,C语言是面向硬件特性,基于模块的一种编程语言。采用更“高级”语言的编程思维并不能实现有效的C程序设计。本书是从C语言的特点,适合C语言开发的设计目标的特点出发,阐述一类C语言的开发方式,并通过设计具体模块,依次展开讨论。如果你想有效地使用C语言,在系统设计中灵活地应用模块化设计思想,本书是一个很不错的参考。

C高级编程 基于模块化设计思想的C语言开发 高清 带书签.pdf

C高级编程 基于模块化设计思想的C语言开发 高清 带书签

【重拾C语言】五、模块化程序设计——函数(定义、调用、参数传递、结果返回、函数原型;典例:打印字符图形、验证哥德巴赫猜想)

本文介绍了模块化程序设计——函数,包括如何定义函数、函数的调用形式和过程、参数传递(值传递和指针传递)、函数结果的返回以及函数原型的使用。具体的程序设计实例有打印字符图形和验证哥德巴赫猜想。

天地玄黄 魑魅魍魉 风花雪月 商角徵羽 2028

关于C语言模块化设计及良好编程习惯的文档

C语言模块化设计资料,主要描述了在做C语言开发时,要形成良好的编写习惯,包括备注、分享符号等,一方面可以提高自己的编写逻辑,另一方面可以让小伙伴看得懂自己的代码,或者3年后可以明白当初自己编程的思路。

【C语言】-模块化设计学习笔记

目录 模块化设计思想 函数 函数的定义 函数的调用 预处理 一、模块化设计思想 在进行程序设计时,把一个大的程序按功能划分为若干小的程序,每个小程序完成一个特定的功能,把这些小程序之间建立必要的联系即可以完成整个程序的功能,这些小的程序就是模块。 通常规定模块只有一个入口和出口,使用模块的约束条件使入口参数和出口参数。 二、函数 2.1 函数的定义 1.库函数(系统定义的标准函数比如printf() scanf()...) 库函数的函数说明或声明一般放在系统的include目录下

menteei的博客 1202

C语言模块化编程

C语言模块化编程

C语言模块化编程(我见过最好的)

C语言模块化编程(我见过最好的),我目前就使用的,觉得不错

【C语言】模块化编程-通俗易懂

1什么是模块化 模块化编程就是把我们的一整个项目,分成很多模块(比如一个学生成绩查询可以分为,登陆,查询,修改保存,退出等模块) 而一个程序工程包含多个源文件(.c 文件和 .h 文件),每个 .c 文件可以被称为一个模块,每一个模块都有其各自的功能,而每一个.h文件则是声明该模块,相当于功能说明书 模块化编程在嵌入式中为必须要掌握的技能 2为啥要用模块化 有的同学会想,我一个main...

Z小旋 4万+

MagicDraw小白必看:BDD图中模块的5种属性详解(含SysML v1.6最新端口配置指南)

本文面向MagicDraw初学者,详细解析SysML BDD图中模块的五种核心结构属性,包括组成部分、引用、值、约束属性及端口。重点阐述了SysML v1.6中端口设计的范式转移,对比了完整端口与代理端口的区别与应用场景,并通过实战案例指导如何利用代理端口进行清晰的接口定义与系统架构设计。

rum55的博客 373

C语言入门:自定义函数的模块化设计原则

模块化设计(Modular Design)是一种将复杂系统分解为多个独立、可交互的 “模块”(这里指自定义函数)的设计方法。每个模块完成单一、明确的功能,模块之间通过接口(函数参数、返回值)通信。// 假设3科成绩int total;// 总分// 输入模块:返回实际输入的学生数量,参数是学生数组和最大容量// 计算模块:无返回值,直接修改结构体中的total字段(传入指针)// 排序模块:使用冒泡排序,传入指针修改数组顺序// 输出模块:无返回值,打印结果拆。

Mr_-G,一名勤奋底层软件开发工程师的博客 974

App inventor2通过蓝牙控制Arduino Uno LED开关

App inventer2控制Arduino Uno LED开关 如果学会这个小程序,大部分的手机通过蓝牙控制Arduino的功能都可以实现,这个小示例是通过蓝牙模块向Arduino发送"0"和"1",而其它功能要发送其它不同的字符串内容给Arduino. 所需硬件: Arduino Uno JDY-16 蓝牙模块(我的是蓝牙4.2版本) 草帽LED(可选) 手机(我用的是安卓,苹果手机应该也可以,最近其应用商店也有App inventor(AI)伴侣) 软件: Aduino IDE或者Platfom

Firmin123456的博客 5498

IMU卡尔曼滤波方法详细介绍

本文介绍了基于IMU和卡尔曼滤波的状态估计方法。系统采用9维状态向量(位置、速度、加速度计零偏),通过牛顿运动学建立状态方程,并利用外部位置观测进行校正。详细推导了状态转移矩阵和控制输入矩阵的形式,阐述了预测和更新的计算步骤。同时说明了过程噪声Q和观测噪声R的设置原则,其中Q反映模型不确定性,R取决于传感器精度。该方法可有效融合IMU测量与外部观测数据,实现位置、速度和偏置的联合估计。

haing2019的博客 757

C语言函数

语法:形参用指针( int *p ),调用时传地址( changeValue(&num) )比如计算两数之和的函数,就像一个“加法工具”,给它两个数(输入),它返回和(输出)。- 如 int (返回整数)、 float (返回小数)、 void (无返回值)- 字符串操作: strlen() (求长度)、 strcpy() (复制字符串)- 内存操作: malloc() (动态分配内存)、 free() (释放内存)- 实参是变量的地址(如 &num ),形参是指针(如 int *p )

d050110的博客 1736

全志T133-s3(Tina Linux)下RTL8723DS WiFi驱动移植与调试实战

本文详细介绍了在全志T133-s3平台(Tina Linux)上移植RTL8723DS WiFi驱动的完整流程,包括硬件连接、驱动源码获取、内核配置、系统适配、设备树配置以及常见问题排查。通过实战案例,帮助开发者快速解决SDIO接口通信、固件加载、电源管理等关键问题,实现稳定的WiFi功能。

weixin_30505225的博客 507

C语言中关于函数的总结

C语言中关于函数的总结知识点敲黑板先看这里函数意义函数参数 知识点 函数意义、 函数参数、 函数设计原则、 函数与宏 敲黑板先看这里 你觉不觉得C语言基础知识概念在头脑里没有形成知识体系?是否比较模糊比较乱?这就对了?我之前也是,有些知识点时间长了容易忘或者混淆,有些初学者抓不住重点觉得C语言复杂,难!实不相瞒,我也是这样的感受,于是我想是时候整体的把C语言给好好的总结一下了,这样形成一个知识体...

qq_45142474的博客 1080

原创_新魔百和CM201-1鸿蒙架构当贝乐家语音安卓9线刷固件包刷机教程可救砖rom刷机包

不用担心变砖,因为系统内核会自动判断分区及CPU等级,假设你CPU是高于S905L3的那么。7.adb功能支持,系统增加开机自启功能,添加老人桌面模式,默认为年轻化桌面;所以我发的这个固件可适用于_cw_ys_zg_zn代工上生产的盒子进行刷机;5.CPU及GPU算法更改,当观看4K片源时,AI智能会自动优化系统后台进程,正如我所说,本固件是采用安卓公版镜像制作而成,那么代工厂也是使用的公版镜像,1.移植鸿蒙架构代码,完美融合安卓系统,增加系统的稳定性;刷机的时候 他会自动短接链接,所以不存在变砖。

a138088150的博客 1万+

IBTrACS v04r01 数据提取实战:Pandas 筛选 JTWC/CMA/JMA 3机构最佳路径数据

本文详细介绍了如何使用 Pandas 高效提取和处理 IBTrACS v04r01 数据集中的最佳路径数据,特别针对 JTWC、CMA 和 JMA 三家权威机构的数据进行对比分析。通过构建可复用的数据提取函数,解决多机构数据质量差异问题,并提供高级分析与可视化应用示例,助力热带气旋研究。

clijovtbq401783153的博客 515

【C 语言入门】从零开始:彻底理解 C 语言函数的本质与实战

完整声明格式返回值类型 函数名(参数列表) {// 函数体:执行语句[return 表达式;] // 可选,无返回值时省略(返回值类型为void)关键组成部分返回值类型可以是基本类型(intcharfloat)、指针类型或void(无返回值)。必须与return语句表达式类型一致(可自动隐式转换,如对int返回值类型,会截断为3函数名遵循标识符规则(字母 / 数字 / 下划线,不能以数字开头),建议用动词 + 名词命名(如参数列表可包含多个参数,用逗号分隔,每个参数需指定类型(如。

2501_91602899的博客 869

Android Framework之Pkms详解

system 用户并没有访问应用程序目录的权限,但是 Installd 服务是以 root 用户启动的,可以访问 /data/data/ 下的目录,Installd 需要完成一些创建应用数据的任务。Installer 服务是 Android 提供的用于安装的服务,Installer 持有 Installd 守护进程对应的 Binder 服务的代理对象,本质上是通过 Binder 通信调用底层的 Installd 服务真正完成 APK 文件格式的优化和转换、建立相关的数据目录、删除文件、安装应用等工作。

门徒07的博客 1842

Day05 郝斌C语言自学视频之C语言的函数

这篇笔记主要是介绍C语言中的函数,包括函数的功能和定义等。阅读本文预计需要 6 分钟。 Day05 郝斌C语言自学视频之C语言的函数为什么需要函数什么是函数函数的分类如何定义使用函数定义函数如何在软件开发中合理的设计函数来解决实际问题变量的作用域和存储方式常用的系统函数后记 为什么需要函数 函数是C语言的基本单位,类是Java,C#,C++的基本单位。函数是继学习 C 语言流程控制之后的第二个...

Jock2018的博客 515

【测绘程序设计】——潮汐调和分析

最小二乘潮汐调和分析源码、使用示例及数据

C_xxy's blog 2652

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

C语言笔记归纳5:函数

库函数不能满足所有需求,自定义函数是 “按需设计的工具”,核心掌握 “语法结构 + 形参实参 + return 语句”。返回值类型 函数名(形式参数列表)函数体;// 实现功能的代码return 结果;// 返回计算结果(返回值类型非void时必须有)// 加法函数:接收两个int型“原材料”,返回int型“产品”int Add(int x, int y) // x、y是形式参数(形参)// 生产流程:求和,返回结果int main()// 修正原笔记笔误:scnf→scanf。

yonakaame的博客 971

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

上一篇: 【C语言入门】函数指针:定义与使用(指向函数的指针变量)
下一篇: 【C语言入门】回调函数:通过函数指针实现的逆向调用
Mr_-G
Mr_-G 优质创作者: 嵌入式与硬件开发技术领域 优质创作者: 嵌入式与硬件开发技术领域
博客等级 码龄6年 7917粉丝 416原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值