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

AVR架构下无需单独命名字符串将字符数组存入PROGMEM的方法

AVR下无需单独命名字符串的PROGMEM数组初始化方案

核心修改思路

直接利用AVR GCC的PROGMEM属性和<avr/pgmspace.h>工具链,在指针数组定义时直接嵌入字符串字面量,无需单独为每个字符串命名,同时将数组及字符串全部存储到程序存储器中。

步骤1:修改数组定义

先包含必要的头文件,再将原指针数组修改为带PROGMEM修饰的const char * const类型数组:

#include <avr/pgmspace.h>

// 直接在数组中嵌入字符串字面量,无需单独命名
static const char * const num_tab[] PROGMEM = {
    "First",
    "Second",
    "Third"
};

static const char * const day_tab[] PROGMEM = {
    "Sunday",
    "Monday",
    "Tuesday"
};

static const char * const random_tab[] PROGMEM = {
    "Strings and arrays can have",
    "diferent",
    "lenghts"
};

关键说明:

  • const char * const:第一层const保证字符串内容不可修改,第二层const保证数组内的指针不可修改,符合PROGMEM存储的只读特性
  • 末尾的PROGMEM:告诉编译器将整个指针数组(包括其中的字符串指针)存储到程序存储器,同时编译器会自动将数组内的字符串字面量也放入PROGMEM,无需手动逐个标记

步骤2:修改读取函数

由于AVR无法直接返回PROGMEM中的字符串指针(需复制到RAM缓冲区),需使用pgmspace.h提供的专用函数完成读取:

方案1:使用静态缓冲区(单线程场景适用)

const char * dayName(int index) {
    // 根据最长字符串长度调整缓冲区大小,需包含终止符
    static char buffer[32];
    // 索引合法性检查,避免越界访问
    if (index < 0 || index >= sizeof(day_tab)/sizeof(day_tab[0])) {
        strcpy(buffer, "Invalid");
        return buffer;
    }
    // 从PROGMEM读取字符串到RAM缓冲区
    strcpy_P(buffer, (PGM_P)pgm_read_word(&day_tab[index]));
    return buffer;
}

方案2:调用者提供缓冲区(多任务/长字符串场景适用)

避免静态缓冲区的覆盖问题,让调用者自行管理缓冲区:

void dayName(int index, char *buffer, size_t buffer_size) {
    if (index < 0 || index >= sizeof(day_tab)/sizeof(day_tab[0])) {
        // 安全复制,避免缓冲区溢出
        strncpy(buffer, "Invalid", buffer_size - 1);
        buffer[buffer_size - 1] = '\0';
        return;
    }
    // 从PROGMEM复制字符串到指定缓冲区
    strncpy_P(buffer, (PGM_P)pgm_read_word(&day_tab[index]), buffer_size - 1);
    buffer[buffer_size - 1] = '\0';
}

关键说明:

  • pgm_read_word(&day_tab[index]):读取PROGMEM中指针数组的第index个元素(即指向目标字符串的指针)
  • strcpy_P/strncpy_P:AVR专用的字符串复制函数,用于从PROGMEM读取内容到RAM,替代标准库的strcpy/strncpy
  • PGM_P:<avr/pgmspace.h>定义的类型,等价于const char PROGMEM *,用于标记指向PROGMEM字符串的指针

注意事项

  • 必须包含<avr/pgmspace.h>头文件,所有PROGMEM相关的函数、宏和类型都依赖它
  • 缓冲区大小需足够容纳目标数组中最长的字符串(包括终止符\0)
  • 务必添加索引合法性检查,越界访问PROGMEM会导致程序异常
  • 若使用静态缓冲区,单线程环境下无问题,但多任务场景可能出现内容覆盖,建议优先使用调用者提供缓冲区的方案

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 17:47:26