"部分类型冲突"由于GCC 4.8.2中的宏定义

时间:2015-05-04 14:19:03

标签: c arduino

我得到了"部分类型冲突"如果我在内联函数中调用一个宏。 在WWW中没有任何关于此错误的信息。

宏的目的是提供一个宏来处理为Arduino保存在flash中的字符串(只是一个侧面信息)。 如果函数没有内联,一切都很好。可能是什么原因?

#undef PROGMEM
#define PROGMEM __attribute__(( section(".progmem.data") ))

#undef PSTR
/* need to define prog_char in avr-gcc 4.7 */
#if __AVR__ && __GNUC__ == 4 && __GNUC_MINOR__ > 6
typedef char prog_char;
#endif
/* Need const type for progmem - new for avr-gcc 4.6 */
#if __AVR__ && __GNUC__ == 4 && __GNUC_MINOR__ > 5
#define PSTR(s) (__extension__({static const prog_char __c[] PROGMEM = (s); \
                                  (const prog_char_t *)&__c[0]; }))
#else
#define PSTR(s) (__extension__({static prog_char __c[] PROGMEM = (s); \
                                  (prog_char_t *)&__c[0]; }))
#endif

代码:

inline void test() {
    hal.console->println("AP_Common tests\n");
    hal.console->println_P(PSTR("AP_Common tests\n") );
    hal.console->printf_P(PSTR("AP_Common tests\n") );
}

void setup(void)
{
  test();
}

void loop(void)
{
    // do nothing
}

错误:" println_P(PSTR(" Bad var table \ n"));"

AP_HAL/utility/BetterStream.h:53:57: note: in definition of macro 'printf_P'
 #define printf_P(fmt, ...) _printf_P((const prog_char *)fmt, ## __VA_ARGS__)
                                                         ^
output_debug.h:13:26: note: in expansion of macro 'PSTR'
   hal.console->printf_P( PSTR("{\"t\":\"s_cmp\",\"h\":%.1f}\n"),
                          ^
AP_Progmem/AP_Progmem_AVR.h:25:56: note: '__c' was declared here
 #define PSTR(s) (__extension__({static const prog_char __c[] PROGMEM = (s); \
                                                        ^
AP_HAL/utility/BetterStream.h:53:57: note: in definition of macro 'printf_P'
 #define printf_P(fmt, ...) _printf_P((const prog_char *)fmt, ## __VA_ARGS__)
                                                         ^
AP_test.ino:60:27: note: in expansion of macro 'PSTR'

编辑:

在两次派生类中调用PSTR()会导致同样的问题。 我认为这是一个编译器错误,导致未定义的行为。

1 个答案:

答案 0 :(得分:2)

尝试:PROGMEM static const prog_char __c[]。奇怪的是,我发现属性必须在声明之前。不确定你的版本实际上做了什么。这可能就是问题所在。

或者:section类型是存储值的locical memory部分的属性。我想这是由链接器报告的。 PROGMEM部分默认为NOLOAD(这部分是有意义的)。但是,由于初始化,编译器要求该部分相反,从而导致错误。即使这不是真的,我也会在这方面搜索问题。

其他一些评论:

  • 使用stdint类型,不要依赖内置类型的大小。
  • 小心'char'。仅用于实际字符,不依赖于他们的签名。如果你不得不关心另一种类型(uint8_t或int8_t)会更合适。
  • `#undef'宏不是在使用之前,而是在之后。否则,意外的重新定义可能会在没有警告的情况下通过。这些错误很难调试!改为在标题中使用警卫。
  • 在微控制器中, const-correctness 至关重要,因此请明智地使用它。 要避免const,即使这会花费更多精力(直到您获得更多经验)。这不仅可以检测编译时的常见缺陷,还可以节省RAM和(甚至可能)Flash,因为非常量变量存储在RAM中,并且Flash中有初始化值。
  • 不要在custon代码中使用__ - 前缀。这些应该保留给工具链的编译器和系统库。您可以将此作为后缀使用(但为什么在示例中?)
  • 避免使用类型转换。初学者代码中的大多数演员实际上都是不必要的,或者是界面设计不良的症状。基本上:如果您不必指定函数的参数类型,则不需要类型转换。 (是的,有一些例外 - 这就是我称之为基本规则而不是法律的原因。)
  • 一般情况下:使用编译器提供的所有帮助。嵌入式调试并不是很有趣。