为啥 AVR-GCC 编译器在使用相同的变量但作为 PROGMEM 重载时会引发错误?

Posted

技术标签:

【中文标题】为啥 AVR-GCC 编译器在使用相同的变量但作为 PROGMEM 重载时会引发错误?【英文标题】:Why AVR-GCC compiler throws an error when overloading with the same variables but as PROGMEM?为什么 AVR-GCC 编译器在使用相同的变量但作为 PROGMEM 重载时会引发错误? 【发布时间】:2021-07-31 17:22:48 【问题描述】:

我的问题更像是:为什么编译器“认为” “PROGMEM 变量”“普通变量” 相同>?是因为PROGMEM-keyword is "just" a macro 仅此而已吗?还是出于其他原因? 是否有任何解决方法..?

问题演示:

让我们考虑下面的例子:

class object 
public:
  object(int* variable);
  object(int* variable PROGMEM);
;

它抛出 error: 'object::object(int*)' cannot be overloaded 就好像它是一样的。

sketch_jul31a:4:3: error: 'object::object(int*)' cannot be overloaded

   object(int* variable PROGMEM)

   ^~~~~~

sketch_jul31a:3:3: error: with 'object::object(int*)'

   object(int* variable)

   ^~~~~~

exit status 1
'object::object(int*)' cannot be overloaded

结尾:

我前段时间在开发图书馆时遇到了这个问题,我在 arduino-forum 上问过这个问题,但我没有任何答案,所以我想了很长时间后才问过一次再次,在这里。

【问题讨论】:

该注释对于作为普通值的函数参数没有意义。重载指向程序的指针与指向数据内存的指针是有道理的,但这必须是指针类型的一部分——不记得是否有注释。 PROGMEM 是链接器存储变量的信息。它与变量类型无关。 @Mat 这是我的错,我在发布之前忘记了 * 哈哈 @Juraj 太可悲了.. 这正是我所期待的答案... 我希望有一个解决方法...... 【参考方案1】:

您不能期望编译器将链接器部分视为类型限定符,但您可以为 const int* 定义重载,这非常接近 PROGMEM(ROM 位置)的语义。

我想知道你打算用const int* 做什么。你所能做的就是读取它,所以它基本上相当于一个普通的常量int 值,增加了两个字节的 ROM 成本。

【讨论】:

太棒了!const int* variable PROGMEM 这样的东西是有意义的,因为PROGMEM 无论如何都是不变的。这只是我的一个“愚蠢”示例,在我的情况下 i had to store a banch of weights and biases (如果 PROGMEM 用于只读目的),但最后我逃脱了 MACROS.. 我明白了。很高兴能帮到你:)【参考方案2】:

__attribute__((progmem)) 是编译器功能,而不是 C++ 语言功能,因此它不参与重载决议。 object(int variable);object(int variable PROGMEM); 在 C++ 中看起来像是 object(int variable); 的双重声明。

【讨论】:

以上是关于为啥 AVR-GCC 编译器在使用相同的变量但作为 PROGMEM 重载时会引发错误?的主要内容,如果未能解决你的问题,请参考以下文章

avr-gcc:(看似)简单功能中不需要的序言/尾声

avr-gcc:如何将 __attribute__((address)) 与 EEMEM 一起使用?

为啥相同的代码相同的编译器在不同电脑上的运行结果不同?

为啥 C# 在多态中不考虑函数的返回类型?

为啥 == 在比较具有相同 int 值的两个对象类型变量时不起作用

为啥我编译的MFC应用程序在其他电脑上不能运行?