C++ AVR GCC本地阵列初始化

C++ AVR GCC本地阵列初始化,c++,c,gcc,avr,C++,C,Gcc,Avr,我要初始化本地常量数组: void foo() { const uint8_t arr[] = {1, 2, 3, 4, 5}; } 对于这个初始化,我支付了5字节的全局RAM:这5个常量在程序开始时被复制到RAM中,并且永远留在那里。 问题是为什么?当我调用函数时,编译器不能直接从FLASH初始化数组吗? 无论如何,我不能在其他任何地方使用右手临时数组,它必须立即销毁;但在启动后,它始终存在于RAM中。 现在我必须做一些类似的事情 void foo() { static co

我要初始化本地常量数组:

void foo() {
    const uint8_t arr[] = {1, 2, 3, 4, 5};
}
对于这个初始化,我支付了5字节的全局RAM:这5个常量在程序开始时被复制到RAM中,并且永远留在那里。 问题是为什么?当我调用函数时,编译器不能直接从FLASH初始化数组吗? 无论如何,我不能在其他任何地方使用右手临时数组,它必须立即销毁;但在启动后,它始终存在于RAM中。 现在我必须做一些类似的事情

void foo() {
    static const uint8_t init_arr[] PROGMEM = {1, 2, 3, 4, 5};
    uint8_t arr[5];
    copy_from_prog_function(arr, init_arr, 5);
}
最重要的是,现在我甚至不能让我的arr成为const


这个问题还有更优雅的解决方案吗?

正如您可能知道的,AVR是哈佛体系结构-程序驻留在不同的地址空间中,而数据和访问它的指令是不同的。C没有不同地址空间的方法,所以您必须在这里使用类似于这个PROGMEM宏的编译器扩展

由于程序内存只能按字节读取,而且比RAM慢一点,因为它由闪存支持,所以编译器永远不会自动将数据放在内存中。另请参见avr libc文档,特别是关于const的注释

也就是说,如果数组是const,为什么不声明它是静态的呢?然后编译器不会创建代码将其复制到堆栈上,您可以直接访问它,但仍在RAM中

如果希望它驻留在程序内存中,只需像在第二个示例中那样声明它,并使用pgm_read_byte宏访问各个元素,无需自己复制整个数组


正如所建议的,使用较新的AVR工具链,您甚至可以使用直接闪存访问,因此代码看起来更漂亮。

我怀疑这与哈佛体系结构的一些废话有关。在这种情况下,你基本上在问,是否有任何使用AVR的优雅方式,而对于市场上所有其他8位强化剂,答案是否定的。可能需要考虑切换到像ARM一样的二十一世纪CPU内核。@ LundIn GCC有一个非常好的扩展名为命名地址空间。顺便说一句,我已经多年没有使用AVR了,因为markerIt上有更强大、更便宜的32位微处理器,这是一种有点过时的方式。更新的ie不到5年的gcc版本有名为命名地址空间的扩展,访问更容易。只需使用uu flash前缀constuint6 uu flash a[]={1,2,3,4,5}。更多细节@PeterJ_01尼斯语法糖,我还没看过。总之,它归结为相同的机制,只是使代码看起来更容易:当然是这样,但实际上它使访问变得更容易,而且C:。指针处理也简单得多。现在是编译器的问题,而不是编码器的问题。我只是用AS7编译。没问题。不要将IDE视为VisualStudio,因为VisualStudio +一些扩展不知道GCC扩展的任何内容,并且在屏幕上使它们变红,这一特性仅在C中支持,而不是C++。羞耻我不会因为这个而放弃C++,我无法想象任何人都会这样做。