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

README_条件编译笔记

条件编译笔记1. 这篇笔记讲什么这篇笔记不是泛泛而谈 C 语言预处理器而是结合你当前 STM32 工程里的真实代码来讲清楚什么是条件编译它和普通if判断有什么本质区别你的项目里哪些地方正在使用条件编译这些写法分别解决什么问题后面你自己改工程时哪些宏可以改哪些不要随便动工程路径D:\Desktop\STM32_Project_Collection\f407zgt6(hal)\Graduate_Project(物联网rfid正常通讯) -测试2. 什么是条件编译条件编译属于C 预处理器preprocessor的工作。一个.c文件在真正编译成目标代码之前会先经过“预处理”阶段。这个阶段会先处理#include#define#undef#if#ifdef#ifndef#elif#else#endif所以条件编译的本质是在“编译之前”先决定某一段代码到底保不保留。也就是说编译器真正看到的代码已经是“预处理之后”的结果了。3. 条件编译和普通if的区别这是最容易混淆的点。3.1 运行时ifif(flag){func();}特点这段代码一定会参与编译程序运行时才判断flag会产生运行时分支开销3.2 编译时#if#ifLOG_LEVEL1UsartPrintf(...);#endif特点预处理阶段就决定保不保留条件不成立时这段代码会直接从源文件里“消失”不产生运行时判断开销一句话总结if运行时选路径#if编译前选代码这也是为什么单片机项目特别喜欢用条件编译节省 Flash 空间减少串口打印去掉不必要的模块控制不同芯片、不同板型、不同编译选项下的代码分支4. 你这个项目里条件编译主要分哪几类结合工程里的实际代码可以大致分为 5 类日志等级控制C / C 兼容包装HAL 模块开关与默认参数兜底芯片型号、硬件能力、启动方式相关分支头文件防重复包含这里我把“头文件防重复包含”故意放到后面讲因为它虽然最常见但如果一上来就讲它反而容易把条件编译的核心原理冲淡。我们先把“真的会改变功能路径”的几类理解透再回来看头文件保护会更顺。5. 日志等级控制这一部分我按你第一次给我那段代码时的讲法重新写得更“拆解式”一点。对应文件D:\Desktop\STM32_Project_Collection\f407zgt6(hal)\Graduate_Project(物联网rfid正常通讯) -测试\APP\bsp_usart.h原代码#ifndefLOG_LEVEL#defineLOG_LEVEL1#endif#ifLOG_LEVEL2#defineLOG_DEBUG(...)UsartPrintf(USART_DEBUG,__VA_ARGS__)#else#defineLOG_DEBUG(...)#endif#ifLOG_LEVEL1#defineLOG_INFO(...)UsartPrintf(USART_DEBUG,__VA_ARGS__)#else#defineLOG_INFO(...)#endif#defineLOG_WARN(...)UsartPrintf(USART_DEBUG,__VA_ARGS__)#defineLOG_ERROR(...)UsartPrintf(USART_DEBUG,__VA_ARGS__)这段代码的目的很简单用LOG_LEVEL控制日志输出等级在编译阶段决定哪些日志代码保留哪些日志代码直接删掉也就是说它不是“运行时判断要不要打印”而是“编译前就决定这行代码存不存在”。5.1#ifndef LOG_LEVEL是什么意思#ifndefLOG_LEVEL#defineLOG_LEVEL1#endif等价理解如果LOG_LEVEL没有被定义那就给它一个默认值1这里的作用是设置默认日志等级。比如如果你在别处没有写#define LOG_LEVEL 2那这里就自动使用1所以它是一种“默认配置兜底”。5.2#if LOG_LEVEL 2是什么意思#ifLOG_LEVEL2#defineLOG_DEBUG(...)UsartPrintf(USART_DEBUG,__VA_ARGS__)#else#defineLOG_DEBUG(...)#endif等价理解如果日志等级大于等于2那LOG_DEBUG(...)就真的展开成UsartPrintf(...)否则LOG_DEBUG(...)展开成空这里最关键的是“展开成空”。也就是LOG_DEBUG(value%d\r\n,x);当LOG_LEVEL 2时预处理后会直接变成;你也可以粗略理解成这句日志根本不存在了编译器后面看到的代码里已经没有这条调试打印5.3...和__VA_ARGS__是什么这是你这次最关心的点我们把它拆细一点。例如#defineLOG_INFO(...)UsartPrintf(USART_DEBUG,__VA_ARGS__)这里的...表示“参数数量不固定”__VA_ARGS__表示“把传进来的参数原样代入”这叫可变参数宏。也就是说LOG_INFO后面可以接任意数量的参数。例如LOG_INFO(hello\r\n);LOG_INFO(x%d\r\n,x);LOG_INFO(id%d name%s\r\n,id,name);这三种都合法。它们的展开结果分别类似于UsartPrintf(USART_DEBUG,hello\r\n);UsartPrintf(USART_DEBUG,x%d\r\n,x);UsartPrintf(USART_DEBUG,id%d name%s\r\n,id,name);所以你可以把它记成...负责把所有参数“收起来”__VA_ARGS__负责把收起来的参数“原样倒出去”这个理解非常重要。5.4 为什么日志宏这里必须用...因为日志打印本来就像printf有时候只打一段固定字符串有时候打一段格式串加一个变量有时候打一段格式串加多个变量如果不用可变参数宏你就得写很多版本#defineLOG_INFO0(str)...#defineLOG_INFO1(fmt,a)...#defineLOG_INFO2(fmt,a,b)...这样既丑也难维护。而用了#defineLOG_INFO(...)UsartPrintf(USART_DEBUG,__VA_ARGS__)你就能一直保持和printf一样的调用风格。5.5 这段代码在不同LOG_LEVEL下的效果当LOG_LEVEL 0LOG_DEBUG(...)被展开为空LOG_INFO(...)被展开为空LOG_WARN(...)仍然打印LOG_ERROR(...)仍然打印效果只保留警告和错误日志当LOG_LEVEL 1LOG_DEBUG(...)被展开为空LOG_INFO(...)会打印LOG_WARN(...)会打印LOG_ERROR(...)会打印效果打印普通信息、警告、错误不打印调试细节当LOG_LEVEL 2LOG_DEBUG(...)会打印LOG_INFO(...)会打印LOG_WARN(...)会打印LOG_ERROR(...)会打印效果所有日志都打印5.6 用预处理器展开后的直观结果原代码LOG_DEBUG(debug: %d\r\n,a);LOG_INFO(info: %d\r\n,b);LOG_WARN(warn: %d\r\n,c);当LOG_LEVEL 1预处理后大致变成;UsartPrintf(USART_DEBUG,info: %d\r\n,b);UsartPrintf(USART_DEBUG,warn: %d\r\n,c);当LOG_LEVEL 2预处理后大致变成UsartPrintf(USART_DEBUG,debug: %d\r\n,a);UsartPrintf(USART_DEBUG,info: %d\r\n,b);UsartPrintf(USART_DEBUG,warn: %d\r\n,c);所以它的本质就是编译前替换编译前裁剪代码5.7 这种写法的优点5.7.1 没有运行时开销如果写成if(log_level2){UsartPrintf(...);}那么即使不打印程序运行时也还要判断一次。而条件编译是不满足条件时直接不生成这部分代码所以运行时更省。5.7.2 适合单片机单片机项目通常很关心Flash 空间RAM 空间串口打印耗时实时性日志太多会影响速度条件编译正好适合做裁剪。5.7.3 管理方便只改一处#defineLOG_LEVEL2就能控制整个工程的日志详细程度。5.8LOG_WARN和LOG_ERROR为什么没做条件编译#defineLOG_WARN(...)UsartPrintf(USART_DEBUG,__VA_ARGS__)#defineLOG_ERROR(...)UsartPrintf(USART_DEBUG,__VA_ARGS__)说明作者当前的设计意图是WARN和ERROR永远保留不受LOG_LEVEL限制因为这两类信息通常更重要。如果你以后也想让它们受等级控制也可以改成#ifLOG_LEVEL1#defineLOG_WARN(...)UsartPrintf(USART_DEBUG,__VA_ARGS__)#else#defineLOG_WARN(...)#endif5.9 这种写法和函数有什么区别例如你可能会想voidLOG_INFO(constchar*fmt,...){...}宏和函数的区别宏预处理阶段替换可以被条件编译直接裁掉没有函数调用开销函数运行时调用即使想关闭日志函数本身通常还在更容易调试类型检查也更清晰所以在嵌入式里高频日志调试开关通常更喜欢用宏。5.10 这一节你最好记住的三句话你可以把日志等级控制先记成下面这三句#ifndef LOG_LEVEL如果没配置日志等级就给一个默认值。...表示这个宏可以接收不定数量参数。__VA_ARGS__把这些参数原样传给UsartPrintf。再加最后一句总纲这套日志宏不是在运行时决定“打不打印”而是在编译前决定“这行代码还在不在”。6. C / C 兼容包装在这些文件里很常见D:\Desktop\STM32_Project_Collection\f407zgt6(hal)\Graduate_Project(物联网rfid正常通讯) -测试\APP\cJSON.hD:\Desktop\STM32_Project_Collection\f407zgt6(hal)\Graduate_Project(物联网rfid正常通讯) -测试\Core\Inc\usart.hD:\Desktop\STM32_Project_Collection\f407zgt6(hal)\Graduate_Project(物联网rfid正常通讯) -测试\Core\Inc\gpio.h典型写法#ifdef__cplusplusexternC{#endif/* C 函数声明 */#ifdef__cplusplus}#endif6.1 作用如果这个头文件被 C 工程包含C 编译器会自动做名字修饰name mangling。这样会导致C 里实现的函数名和 C 编译器理解的函数名不一致最终链接失败。extern C的作用就是告诉 C这些函数按 C 的方式导出名字不要改名。6.2 为什么要用#ifdef __cplusplus因为在 C 编译器里__cplusplus根本不存在只有 C 编译器才会定义它所以这个条件编译的意思是如果当前是 C 编译就加extern C如果当前是 C 编译就什么都不加这是一种很典型的“跨语言兼容条件编译”。7. HAL 默认参数兜底位于D:\Desktop\STM32_Project_Collection\f407zgt6(hal)\Graduate_Project(物联网rfid正常通讯) -测试\Core\Inc\stm32f4xx_hal_conf.h典型写法#if!defined(HSE_VALUE)#defineHSE_VALUE25000000U#endif类似的还有HSI_VALUELSE_VALUELSI_VALUEHSE_STARTUP_TIMEOUTEXTERNAL_CLOCK_VALUE7.1 这类写法在干什么它是在做“有定义就用你的没有就给默认值”。也就是说如果你在工程选项或别的头文件里已经定义了HSE_VALUE那这里就不会重新定义如果你没定义这里才补一个默认值7.2 好处这种写法很适合做“通用配置模板”同一份 HAL 配置文件可以适应不同板子也允许上层工程覆盖默认值7.3 这和普通#define的区别普通#define HSE_VALUE ...是强制赋值。而#if!defined(HSE_VALUE)#defineHSE_VALUE...#endif是“未定义才赋值”更灵活也更安全。8. HAL 模块开关同样主要位于D:\Desktop\STM32_Project_Collection\f407zgt6(hal)\Graduate_Project(物联网rfid正常通讯) -测试\Core\Inc\stm32f4xx_hal_conf.h典型形式#ifdefHAL_GPIO_MODULE_ENABLED#includestm32f4xx_hal_gpio.h#endif还有很多类似HAL_RCC_MODULE_ENABLEDHAL_DMA_MODULE_ENABLEDHAL_UART_MODULE_ENABLEDHAL_TIM_MODULE_ENABLEDHAL_SPI_MODULE_ENABLEDHAL_I2C_MODULE_ENABLED8.1 作用这类条件编译是在控制某个 HAL 模块要不要参与编译某个头文件要不要被包含8.2 为什么这么做STM32 HAL 很大如果所有模块都打开编译更慢代码更大依赖更多所以 ST 的设计思路是先定义“启用哪些模块”再按宏去包含对应头文件和功能8.3 对你项目的意义你当前项目主要用到GPIOUARTTIMSPII2C所以 HAL 配置里这些启用宏直接决定底层库参与程度。9. 芯片型号和硬件能力判断这类多见于D:\Desktop\STM32_Project_Collection\f407zgt6(hal)\Graduate_Project(物联网rfid正常通讯) -测试\Core\Src\system_stm32f4xx.cCMSIS 头文件和驱动头文件例如常见会看到#ifdefined(STM32F407xx)...#endif或#if(__FPU_PRESENT1)(__FPU_USED1)...#endif9.1 作用根据不同芯片、不同硬件能力决定启动文件怎么配时钟树怎么配向量表位置怎么配FPU 要不要打开某些寄存器功能是否存在9.2 为什么必须用条件编译因为这些差异是“编译前就确定”的不是运行时才知道。比如你用的是STM32F407ZGT6它支持哪些外设、寄存器、FPU这些都取决于芯片型号这不是程序跑起来以后才能判断的事情所以必须用条件编译。10.defined(...)和#ifdef的关系你项目里两种都能看到。10.1#ifdef#ifdef__cplusplus...#endif等价于#ifdefined(__cplusplus)...#endif10.2#ifndef#ifndefLOG_LEVEL...#endif等价于#if!defined(LOG_LEVEL)...#endif10.3 什么时候用哪种经验上判断一个宏是否存在#ifdef/#ifndef更直观多条件组合判断#if defined(...) !defined(...)更灵活所以你会看到简单判断用#ifdef复杂判断用#if defined(...)11. 你的项目里“不是条件编译但容易误以为是”的内容比如很多地方有#definePASSWORD_MAX_COUNT12#defineSCREEN_MODE_FACE_RFID1#defineSERVO_UNLOCK_US2000这些不是条件编译。它们只是普通宏常量用来在编译前做文本替换。区别在于普通宏替换值条件编译决定代码保不保留所以#defineA10不是条件编译。而#ifA5...#endif才是条件编译。12. 头文件防重复包含现在再回头看这类写法就会更容易理解它为什么也是条件编译。例如D:\Desktop\STM32_Project_Collection\f407zgt6(hal)\Graduate_Project(物联网rfid正常通讯) -测试\APP\bsp_usart.hD:\Desktop\STM32_Project_Collection\f407zgt6(hal)\Graduate_Project(物联网rfid正常通讯) -测试\APP\serial_screen.hD:\Desktop\STM32_Project_Collection\f407zgt6(hal)\Graduate_Project(物联网rfid正常通讯) -测试\Core\Inc\main.h典型写法#ifndefBSP_USART_H#defineBSP_USART_H/* 头文件内容 */#endif12.1 它的作用防止同一个头文件被重复包含两次以上。比如main.c包含了bsp_system.hbsp_system.h又包含了bsp_usart.h另一个头文件也可能再次包含bsp_usart.h如果没有这层保护编译器就可能看到重复的类型定义重复的函数声明重复的宏定义然后报错。12.2 它为什么属于条件编译因为这里本质是在问BSP_USART_H这个宏定义过了吗如果没定义就编译头文件内容如果已经定义过就跳过整份头文件所以它虽然看起来像模板但本质仍然是条件编译。12.3 为什么这部分放到后面讲因为头文件保护更像一种“工程卫生习惯”。它当然很重要但它没有前面那些例子那么直接地体现“功能裁剪”和“编译前选代码”的味道。先理解日志等级、模块开关、芯片差异再回来看头文件保护会更容易把它放进整体框架里理解而不是只把它背成一个固定模板。13. 为什么单片机项目特别依赖条件编译你的这个毕设项目里条件编译非常合理原因包括13.1 资源有限STM32 的FlashRAM串口带宽调试时间都比较宝贵。所以像调试日志开关模块按需启用芯片特性差异裁剪这些都适合在编译阶段处理掉。13.2 同一份代码要兼容不同环境例如调试版 / 发布版C 编译 / C 编译不同晶振参数不同芯片型号这些差异最适合靠条件编译管理。13.3 比运行时判断更干净对于很多底层功能如果这个模块不用最好连代码都不要编进去而不是留着代码到运行时再判断不用。14. 你现在这个项目里最值得你自己掌握的条件编译点如果从“后面你自己维护项目”的角度看最值得掌握的是这 4 类14.1 日志等级文件D:\Desktop\STM32_Project_Collection\f407zgt6(hal)\Graduate_Project(物联网rfid正常通讯) -测试\APP\bsp_usart.h你最可能自己改的是#defineLOG_LEVEL1改成0只保留警告和错误1显示普通信息2连调试日志都显示14.2 HAL 模块开关文件D:\Desktop\STM32_Project_Collection\f407zgt6(hal)\Graduate_Project(物联网rfid正常通讯) -测试\Core\Inc\stm32f4xx_hal_conf.h这决定哪些 HAL 模块参与编译。14.3 晶振和超时参数默认值还是D:\Desktop\STM32_Project_Collection\f407zgt6(hal)\Graduate_Project(物联网rfid正常通讯) -测试\Core\Inc\stm32f4xx_hal_conf.h如果你以后换板子外部晶振不是当前值这一类就可能要跟着变。14.4 芯片型号宏一般由工程编译选项或 CMSIS 头文件体系决定比如STM32F407xx这类不要随便手改除非你真的换了芯片。15. 改条件编译时要特别小心什么15.1 不要把头文件保护删掉像#ifndefXXX_H#defineXXX_H...#endif这种看起来像模板但它是必须的。15.2 不要随便关 HAL 模块如果你把HAL_UART_MODULE_ENABLED之类的宏关掉可能会导致编译不过某些 HAL 头文件没包含某些底层函数声明消失15.3 不要误把条件编译当运行时逻辑例如日志宏改LOG_LEVEL会改变“编译出来的代码”不是程序运行时动态切换也就是说改了LOG_LEVEL后需要重新编译效果才会生效。15.4 芯片相关宏不要乱改像STM32F407xx__FPU_PRESENT__FPU_USED这类宏跟芯片和工具链配置绑定乱改会导致系统初始化异常甚至启动都不正常。16. 一个简单总结如果把你这个项目里的条件编译压缩成一句话可以这样理解条件编译就是“在编译之前用宏决定哪些代码存在哪些代码不存在”。在你的项目里它主要承担了这些职责控制日志输出等级做 C / C 兼容给 HAL 配置默认值按芯片能力启用或裁剪底层代码防止头文件重复包含所以条件编译不是“高级小技巧”而是嵌入式工程非常核心的一部分。17. 你后面可以怎么继续学如果你想把这一块真正吃透建议按这个顺序继续先彻底吃透#define、#ifdef、#ifndef、#if defined(...)再理解可变参数宏比如__VA_ARGS__然后学会区分编译时配置运行时状态最后再去看更复杂的跨平台头文件和 HAL / CMSIS 配置头18. 本项目里建议你重点查看的文件如果你想结合实际代码再读一遍最推荐这几个D:\Desktop\STM32_Project_Collection\f407zgt6(hal)\Graduate_Project(物联网rfid正常通讯) -测试\APP\bsp_usart.hD:\Desktop\STM32_Project_Collection\f407zgt6(hal)\Graduate_Project(物联网rfid正常通讯) -测试\APP\cJSON.hD:\Desktop\STM32_Project_Collection\f407zgt6(hal)\Graduate_Project(物联网rfid正常通讯) -测试\Core\Inc\stm32f4xx_hal_conf.hD:\Desktop\STM32_Project_Collection\f407zgt6(hal)\Graduate_Project(物联网rfid正常通讯) -测试\Core\Src\system_stm32f4xx.cD:\Desktop\STM32_Project_Collection\f407zgt6(hal)\Graduate_Project(物联网rfid正常通讯) -测试\Core\Inc\usart.h19. 最后一句最好记的话你可以先把条件编译记成下面这句话if是程序运行时做选择#if是编译器在编译前帮你删代码。这句话一旦真正理解了你后面再看 STM32、HAL、CMSIS 里的宏配置就会顺很多。

相关文章:

README_条件编译笔记

条件编译笔记 1. 这篇笔记讲什么 这篇笔记不是泛泛而谈 C 语言预处理器,而是结合你当前 STM32 工程里的真实代码来讲清楚: 什么是条件编译它和普通 if 判断有什么本质区别你的项目里哪些地方正在使用条件编译这些写法分别解决什么问题后面你自己改工程时…...

如何在PS4上轻松管理1490款游戏作弊代码:GoldHEN Cheats Manager完整指南

如何在PS4上轻松管理1490款游戏作弊代码:GoldHEN Cheats Manager完整指南 【免费下载链接】GoldHEN_Cheat_Manager GoldHEN Cheats Manager 项目地址: https://gitcode.com/gh_mirrors/go/GoldHEN_Cheat_Manager GoldHEN Cheats Manager是一款专为PlayStatio…...

GetQzonehistory:一站式自动化QQ空间历史数据备份解决方案

GetQzonehistory:一站式自动化QQ空间历史数据备份解决方案 【免费下载链接】GetQzonehistory 获取QQ空间发布的历史说说 项目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory 在数字记忆日益重要的今天,如何安全高效地备份个人社交…...

3分钟学会:Windows上如何免费安装安卓应用?APK-Installer终极指南

3分钟学会:Windows上如何免费安装安卓应用?APK-Installer终极指南 【免费下载链接】APK-Installer An Android Application Installer for Windows 项目地址: https://gitcode.com/GitHub_Trending/ap/APK-Installer 你是否曾经想在Windows电脑上…...

YOLOv8-Pose训练数据准备避坑指南:从Labelme标注到txt格式的完整流程与可视化校验

YOLOv8-Pose训练数据准备全流程:从Labelme标注到可视化校验的避坑实践 在计算机视觉领域,姿态估计任务对数据格式的要求往往比普通目标检测更加复杂。许多开发者在准备YOLOv8-Pose训练数据时,容易在格式转换环节踩坑——可能是关键点顺序错乱…...

MHY_Scanner:你的Windows游戏自动登录助手,告别抢码烦恼

MHY_Scanner:你的Windows游戏自动登录助手,告别抢码烦恼 【免费下载链接】MHY_Scanner MHY扫码登录器,支持从直播流抢码。 项目地址: https://gitcode.com/gh_mirrors/mh/MHY_Scanner 还在为米哈游游戏登录时抢不到二维码而烦恼吗&…...

985硕士CV求职碰壁?别只刷LeetCode了,试试用FastAPI+PyTorch做个能跑的项目放GitHub

985硕士CV求职突围指南:用FastAPIPyTorch打造可展示的实战项目 当你在GitHub上看到一个完整的计算机视觉项目——包含训练脚本、API接口和部署文档——和另一个只有LeetCode刷题记录的仓库同时出现在面试官屏幕前,哪个更能证明工程能力?答案不…...

STM32新手避坑指南:PWM驱动舵机时,为什么你的角度总是不准?

STM32 PWM驱动舵机精度问题全解析:从原理到调试实战 第一次用STM32的PWM功能控制舵机时,看着那个本该精准转动到90度的舵臂在45度和135度之间来回抽搐,我盯着示波器上飘忽不定的波形,突然理解了为什么有些工程师会对着开发板自言自…...

终极指南:10分钟掌握BepInEx游戏插件框架的完整配置与实战应用

终极指南:10分钟掌握BepInEx游戏插件框架的完整配置与实战应用 【免费下载链接】BepInEx Unity / XNA game patcher and plugin framework 项目地址: https://gitcode.com/GitHub_Trending/be/BepInEx BepInEx游戏插件框架是Unity和.NET游戏模组开发者的首选…...

别再手写浮点运算了!Vivado 2023.2里用Floating Point IP核实现e^x和ln(x)的完整流程

高效实现e^x与ln(x):Vivado 2023.2中Floating Point IP核的工程实践 在FPGA开发中,数学函数的高效实现一直是性能优化的关键环节。传统RTL手写浮点运算不仅耗时费力,还容易引入精度问题和时序瓶颈。Vivado提供的Floating Point IP核为这一难题…...

`std::atomic` 的 6 种 memory_order 到底该怎么选——从 store buffer 到 ARM `dmb` 指令,一张决策树解决 90% 的场景

你以为 flag.store(true) 只是一个赋值? 在 ARM Cortex-A76 上,当你写下 flag.store(true) 而没有指定任何 memory_order 时——也就是说编译器替你选了默认的 memory_order_seq_cst——这行看似无辜的 C++ 代码会被翻译成一条 STR 指令加上一条 DMB ISH 指令,后者的作用是…...

TIDAL音乐下载器终极指南:tidal-dl-ng让您轻松收藏高品质音乐

TIDAL音乐下载器终极指南:tidal-dl-ng让您轻松收藏高品质音乐 【免费下载链接】tidal-dl-ng TIDAL Media Downloader Next Generation! Up to HiRes / TIDAL MAX 24-bit, 192 kHz. 项目地址: https://gitcode.com/gh_mirrors/ti/tidal-dl-ng 还在为TIDAL平台…...

配置Claude Code使用Taotoken作为后端大模型服务提供方

配置Claude Code使用Taotoken作为后端大模型服务提供方 Claude Code 是一款广受开发者欢迎的编程助手工具,它默认连接至特定的模型服务。如果你希望使用 Taotoken 平台聚合的多种大模型作为 Claude Code 的后端,可以通过简单的配置来实现。Taotoken 提供…...

Ansys Maxwell 更改默认单位

更单位。Modeler→Units...

【AISMM落地生死线】:为什么83%的企业误读Level 3达标信号?——基于17份真实报告的逆向归因分析

更多请点击: https://intelliparadigm.com 第一章:AISMM模型评估报告解读会 AISMM(AI-Driven Software Maturity Model)是一套面向生成式AI工程化落地的成熟度评估框架,聚焦模型可解释性、推理稳定性、安全对齐性与运…...

Fish Shell技能库:构建高效可复用的命令行工作流

1. 项目概述:一个为命令行注入灵魂的“技能库”如果你是一个重度命令行用户,每天在终端里敲击着ls、cd、git commit这些命令,有没有那么一瞬间,会感到一丝枯燥和重复?或者,当你看到同事行云流水般地敲出一串…...

为claude code配置taotoken聚合端点的详细步骤与注意事项

为Claude Code配置Taotoken聚合端点的详细步骤与注意事项 Claude Code 是一款基于 Claude 模型的编程助手工具,支持通过命令行或桌面应用调用。当您希望使用 Taotoken 平台聚合的模型服务时,需要正确配置其连接端点。本文将详细介绍如何将 Claude Code …...

终极指南:MelonLoader - 通用Unity游戏模组加载器快速上手教程

终极指南:MelonLoader - 通用Unity游戏模组加载器快速上手教程 【免费下载链接】MelonLoader The Worlds First Universal Mod Loader for Unity Games compatible with both Il2Cpp and Mono 项目地址: https://gitcode.com/gh_mirrors/me/MelonLoader Melo…...

基于OpenClaw与SQLAlchemy构建企业级AI运营助手:从概念验证到生产部署

1. 项目概述:一个面向高管的公司运营AI助手如果你是一位CEO、创始人或者高级运营负责人,每天被各种会议、任务、订单风险和团队状态信息淹没,那么你肯定幻想过有一个能理解你自然语言指令的“数字副手”。这个副手不仅能快速回答“公司现在整…...

中小型产品如何利用多模型聚合能力应对不同AI场景

中小型产品如何利用多模型聚合能力应对不同AI场景 对于中小型产品团队而言,将大模型能力融入产品功能是提升竞争力的关键一步。然而,面对市场上众多的模型提供商、各异的API接口以及复杂的计费管理,有限的开发资源常常成为瓶颈。一个常见的困…...

明日方舟2000+高清游戏素材库:创作者的数字艺术宝库

明日方舟2000高清游戏素材库:创作者的数字艺术宝库 【免费下载链接】ArknightsGameResource 明日方舟客户端素材 项目地址: https://gitcode.com/gh_mirrors/ar/ArknightsGameResource 当你在深夜为同人创作寻找一张完美的阿米娅立绘,当你在游戏开…...

助力国产化升级,全面提升道路监控效率

国产化升级,推动道路监控产业转型随着国家对信息安全的重视,国内各大公安、政企机构已进入全面升级国产化平台的实施阶段。根据最新的政策要求,公安和政府部门必须在未来三年内完成平台的国产化替换工作。这一举措不仅是国家信息安全战略的重…...

无心剑中译阿尔弗雷德·布鲁斯·道格拉斯《冬日夕照》

A Winter Sunset 冬日夕照 Alfred Bruce Douglas 阿尔弗雷德布鲁斯道格拉斯 The frosty sky, like a furnace burning, The keen air, crisp and cold, And a sunset that splashes the clouds with gold But my heart to summer turning. 霜天,像燃烧的火炉 凛冽寒冷,刺…...

CentOS7上InfluxDB2保姆级安装与初始化配置(避坑指南)

CentOS7下InfluxDB2实战部署与深度配置指南 在物联网和APM监控领域,时序数据库的选择往往直接决定整个系统的性能上限。作为新一代时序数据库的标杆,InfluxDB2凭借其创新的IOx存储引擎和Flux查询语言,正在重塑时间序列数据处理的标准。本文将…...

光伏运维工具推荐

1.绿虫:聚焦光伏运维数字化领域,核心产品为光伏运维软件及全流程管理系统,可实现远程智能巡检、智能告警、数据分析优化等功能,能提升运维效率、减少故障停机时间,适配多站点集中管理需求,已服务数百家光伏…...

Playnite终极指南:一站式游戏库管理器,统一管理所有游戏平台

Playnite终极指南:一站式游戏库管理器,统一管理所有游戏平台 【免费下载链接】Playnite Video game library manager with support for wide range of 3rd party libraries and game emulation support, providing one unified interface for your games…...

3分钟搞定HS2-HF Patch:终极游戏增强与汉化解决方案

3分钟搞定HS2-HF Patch:终极游戏增强与汉化解决方案 【免费下载链接】HS2-HF_Patch Automatically translate, uncensor and update HoneySelect2! 项目地址: https://gitcode.com/gh_mirrors/hs/HS2-HF_Patch 还在为Honey Select 2的日文界面和有限功能而烦…...

基于Python的Libby图书监控Agent技能:RPA与智能体应用实践

1. 项目概述与核心价值最近在折腾自动化工具链,发现一个挺有意思的开源项目,叫alexpolonsky/agent-skill-libby-book-monitor。乍一看名字有点长,但拆解一下就很清晰了:这是一个为智能体(Agent)设计的技能&…...

别再只盯着AWS了!聊聊Hyperscaler三巨头(AWS/Azure/GCP)之外,还有哪些玩家值得关注

超越三巨头:全球云计算市场中的隐藏冠军与战略选择 当企业开始规划云战略时,AWS、Azure和GCP这三家"超大规模云服务商"(hyperscaler)往往成为默认选项。但全球云市场远比这复杂——根据Gartner最新数据,202…...

超低能耗建筑用外窗传热系数指标研究

超低能耗建筑用外窗传热系数指标研究超低能耗建筑是我国节能建筑发展的重要趋势,适用的外窗传热系数指标是被动式超低能耗建筑用外窗设计的基础,参考国外被动式建筑用外窗设计准则,探讨了国内超低能耗建筑用外窗传热系数指标的确定方法。0 引…...