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

C语言高级笔记

提升方向:

C语言规范问题:

这才是像样的C语言编程规范啊

如何编写美观又规范的嵌入式C代码?

1. 指针部分:

指针的用途说白了就是传递和偏移,还有就是动态内存使用


指针的高级用法,包括指针的指针、函数指针、指针与数组、指针与结构体的深入应用等。

指针数组:本质是数组

1.指针数组的每个元素都是一个一级指针,每个元素都有自己独立的内存地址

2.应用于字符串数组或者动态数组中

const char* str[3] = { "abc", "123", "..." }; for (int i = 0; i < sizeof(str)/sizeof(char *) i++) { cout << str[i] << endl; }

数组指针:本质是指针

1.数组指针指向第一个数组,每个元素都是一个数组

2.简化多维数组的操作和访问

3.函数参数传递,使函数能够接收多个维度的参数,如果实参是一个二维数组的话,形参可以用数组指针去接收

void prit(int (*str)[3], int rows) { for (int i = 0; i < rows; ++i) { for (int j = 0; j < 3; ++j) { cout << str[i][j] << " "; } cout << endl; } } int main() { int str[2][3] = { {1,2,34}, {2,3,5}}; prit(str, 2); return 0; }

指针函数:本质是函数,返回值类型是指针,修改返回值类型的

1.用于返回动态内存分配的返回内存指针

2.链表操作,用于返回新节点或者链表后的节点

3.字符串操作,返回字符串地址

#include <stdio.h> #include <stdlib.h> int* mymalloc() { int* ptr = (int*)malloc(sizeof(int)*5); if (ptr == NULL) { return NULL; } return ptr; } int main() { int* nptr = mymalloc(); for (int i = 0; i< 5; i++) { nptr[i] = i; printf("%d ", nptr[i]); } free(nptr); nptr = NULL; return 0; }

函数指针:本质是指针

1.用于回调函数中,一个函数调用另外一个

2.动态函数选择,可以在运行中动态选择哪个函数运行,配合函数数组使用

3.函数指针可以替代繁琐的Switch-case的使用,简化代码结构

更好的模块化处理,比如形参列表相同的,功能不同的两个函数整合一起,

/*带参数带返回值的函数指针*/ typedef int (*ParamFunction)(int, int); int my_add1(int a, int b) { return (a + b); } int executeGreet(ParamFunction func, int x, int y) { return func(x, y); // 调用函数指针指向的函数 } /*不带参数不带返回值*/ typedef void (*noparamFunction)(); void demo(void) { printf("无参数的函数指针\n"); } //模板 void noparamModel(noparamFunction fun) { fun(); } int main() { int result = executeGreet(my_add1, 5, 3); noparamModel(demo); printf("Result: %d\n", result); return 0; }
动态函数选择
替代Switch - case 当然对于那种case里面只是一句话的就没必要用了,因为你也要创建大量的函数体 #include <stdio.h> // 定义函数指针类型 typedef int (*operation_func)(int, int); // 各种运算函数 int add(int a, int b) { return a + b; } int subtract(int a, int b) { return a - b; } int multiply(int a, int b) { return a * b; } int divide(int a, int b) { return a / b; } int main() { int a = 10, b = 5; const char operator = '+'; // 函数指针数组 operation_func operations[256] = { NULL }; // 初始化函数指针数组 operations['+'] = add; operations['-'] = subtract; operations['*'] = multiply; operations['/'] = divide; // 选择并调用相应的函数 if (operations[(int)operator] != NULL) { int result = operations[(int)operator](a, b); printf("Result: %d\n", result); } else { printf("Invalid operator\n"); return 1; } return 0; }

值传递:

//值传递 void fun(int a, int b) { int temp = 0; temp = a; a = b; b = temp; cout << "a=" << a << endl << "b=" << b << endl; }

指针传递:

//指针传递 void fun(int *a, int *b) { int temp = 0; temp = *a; *a = *b; *b = temp; cout << "a=" << *a << endl << "b=" << *b << endl; }

结构体指针

77

结构体函数指针:功能函数列表

88

二级指针

00

2. 动态内存部分:


深入了解动态内存分配、管理和优化。掌握 `malloc`, `calloc`, `realloc` 和 `free` 函数的使用,以及如何避免内存泄漏和碎片化。

malloc:

/*用于手动分配一块连续的存储空间,需要手动初始化,也是用的最多的一种,最后记得释放内存*/ int* mymalloc(int num) { int* ptr = (int*)malloc(sizeof(int)*num); if (ptr == NULL) return NULL; return ptr; } int main() { int *pt = mymalloc(10); for (int i = 0; i<10; i++) { pt[i] = i; cout << pt[i] << " " << endl; } free(pt); return 0; }

calloc:

/*为某个元素指定分配多大的内存空间,自动分配内存并且初始化为0,适合用于数组和结构体这样的数据结构,最后记得要释放内存*/ / 为N个整型元素分配内存,并初始化为零 array = calloc(n, sizeof(int)); if (array == NULL) { fprintf(stderr, "内存分配失败\n"); return -1; } // 输出数组,检查是否所有元素都初始化为0 for (int i = 0; i < n; i++) { printf("%d ", array[i]); } printf("\n"); // 使用完毕后,释放内存 free(array);

realloc:

/*如果原来分配的内存不够用了,需要分配更大的内存,需要使用realloc,通常需要和malloc搭配使用,最后释放内存*/ int* arr = malloc(5 * sizeof(int)); // 最初为5个整数分配内存 if (arr == NULL) { fprintf(stderr, "内存分配失败\n"); return 1; } int newSize = 10; // 假设我们现在需要一个更大的数组 arr = realloc(arr, newSize * sizeof(int)); // 将数组大小更改为10个整数 if (arr == NULL) { fprintf(stderr, "内存重新分配失败\n"); return 1; }

3. 结构体部分:

最常见的结构体的用法如下:

typedef struct { uint8_t pi_temp[2]; //无源输入外接温度 uint8_t pi_smoke[2]; //无源输入外接烟感 uint8_t pi_manualwarn;//无源输入模拟报警 uint8_t pi_open;//紧急启动 uint8_t pi_close;//紧急关闭 uint8_t pi_mn_aut; //手自动转换 uint8_t pi_reset;//复位 uint8_t pi_mute;//消音 uint8_t pi_readsata; //无源9 uint8_t pi_readsata2; //消音不再起作用 改为无源反馈 } PASSIVE_IN; PASSIVE_IN pi_in;

结构体中套用结构体:

struct Birthday { int year; int month; int day; }; struct Person { char name[50]; struct Birthday birthday; }; struct Person person1 = {"张三", {1990, 5, 20}}; printf("出生年份: %d\n", person1.birthday.year);

位域操作机制结构体中,所有成员共用同一个结构体类型,节省内存空间

struct zjio_channel_config{ rt_uint16_t START_IO : 4;// 0000 pin rt_uint16_t SX_MODE : 2;//发送还是接收 rt_uint16_t BUFFER_TYPE : 4;//数据类型 rt_uint16_t EX_MODE : 2; rt_uint16_t END_IO : 4; };

其他部分:

运算符 优先级:扩单数,移关位,逻三赋逗

括号,单目运算符(++ -- +- !),数学运算(+-*/),移位运算符(<< >>),关系运算(> < == ),位运算(& | ^) ,逻辑运算符(&& || ~),三目运算(num = a ?1:0;),赋值运算(=),逗号运算(,)

http://www.cnnetsun.cn/news/2521051.html

相关文章:

  • Keil C51递归调用警告处理与工程配置详解
  • ARM嵌入式开发中DS-5内存优化与JVM调优实战
  • 大麦网自动化抢票解决方案:告别手动抢票的低效困境
  • fuckZHS:智慧树课程自动化学习脚本深度解析与逆向工程技术实现
  • 可以快速引蜘蛛的蜘蛛池是什么?
  • Webdash API详解:如何通过RESTful接口扩展和集成外部系统
  • Zhui组件库开发指南:从环境搭建到贡献代码的完整路线图
  • Beat Saber版本管理终极解决方案:BSManager完全指南
  • 3分钟搞定系统镜像烧录!Balena Etcher:开源免费的跨平台烧录神器
  • Ventoy主题定制完全指南:让你的启动界面焕然一新!
  • Scribd电子书离线下载:构建个人数字图书馆的一站式自动化解决方案
  • “冠珠·美乐童行”公益行动走进广州市增城区高滩小学,唱响爱、筑就美
  • sdk-manager-plugin历史与演进:从诞生到废弃的完整技术演进路线图
  • 3个真实场景揭秘:res-downloader如何帮你节省90%的视频收集时间
  • 城市交通气候适应:从生物滞留池到透水铺装的工程实践
  • 3D高斯泼溅技术实现实时4D天气模拟
  • 均衡传播算法(EP)原理与硬件实现优势
  • 微信小程序 零工市场服务系统
  • 量子退火与组合优化:LDA框架的创新应用
  • Linux服务与权限安全加固——从“服务起不来“到“安全合规“的5层防御体系
  • 《Sysinternals实战指南》ZoomIt 学习笔记(11.10):键入模式——在桌面上直接打字讲解的最佳实践
  • 为什么选择SecHex-Spoofy?对比5款HWID工具,这款开源神器究竟强在哪里
  • Recipe协议:基于TEE的BFT复制协议设计与优化
  • AI INFRA之NVIDIA GPUDirect节点内和节点间通信原理详解
  • 计算机视觉——九、图像分割
  • PHP 的 resource(如数据库连接、文件句柄)不能被序列化。
  • H3CSE 高性能园区网:生成树保护机制
  • 3大实战技巧:使用mootdx高效获取与处理通达信财务数据
  • 如何快速安装TrollStore:iOS 14-16.6.1设备一键安装的终极指南
  • DevOps 生态介绍(五):玩转SonarQube:代码静态扫描、Bug预警、质量门禁介绍