You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

avr-gcc如何在函数调用时直接将字符串存入PROGMEM?类似Arduino的F()宏

解决方案

完全可以实现类似Arduino F() 宏的效果,无需提前单独声明PROGMEM字符串变量,avr-libc已经提供了现成的实现,也可以自己基于GCC扩展自定义。

步骤1:使用预定义PSTR()宏

avr-libc的 <avr/pgmspace.h> 头文件中已经内置了 PSTR() 宏,刚好满足你单行调用的需求,调用形式如下:

ParAdd(11, PSTR("Name1"));

步骤2:适配函数实现

由于AVR是哈佛架构,Flash(PROGMEM)和RAM的地址空间相互独立,普通的指针访问默认操作的是RAM空间,你需要对ParAdd函数的实现做对应调整:

  • 读取PROGMEM地址中的字符时,不能直接用 ParName[n] 形式,需要调用 pgm_read_byte() 等专用读取函数
  • 如果你使用avr-gcc 5及以上版本,也可以用__flash关键字标记参数,编译器会自动处理PROGMEM读取逻辑:void ParAdd(uint8_t type, const __flash char *ParName)

完整示例代码

#include <avr/pgmspace.h>
#include <stdint.h>

void ParAdd(uint8_t type, const char *ParName){
    // 示例逻辑:逐字符读取PROGMEM中的字符串
    char c;
    while((c = pgm_read_byte(ParName++)) != '\0'){
        // 处理字符逻辑
    }
}

int main (void){
    ParAdd(11,  PSTR("Name1"));
    ParAdd(22,  PSTR("Name2"));
    ParAdd(30,  PSTR("Name3"));
    return 0;
}

实现原理

PSTR() 宏基于GNU C的复合字面量扩展实现,核心逻辑如下:

#define PSTR(s) ((const char *)(&(const char[] PROGMEM) { s }))

(const char[] PROGMEM) { s } 会创建一个带PROGMEM属性的临时字符数组,编译器会直接将其分配到Flash空间,无需提前定义全局变量,返回的指针可以直接作为参数传递给函数。


内容的提问来源于stack exchange,提问作者eSlavko

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 06:57:03