【问题标题】:Common constants for an AVR / Linux GCC C++ projectAVR / Linux GCC C++ 项目的通用常量
【发布时间】:2011-09-07 08:34:11
【问题描述】:

我正在为 Linux + AVR Arduino 项目创建软件。显然,整个工作在 Eclipse 中被分成几个项目(我没有使用 Arduino IDE)。我想为所有这些项目使用常见的,主要是字符串的常量。我还必须腾出微控制器的 RAM,因此需要编译时常量。我如何最好地实施它?我的想法是为这些常量创建一个单独的、仅包含标题的项目。

使用:

class A {
public:
    static const char * const STRING;
    static const unsigned char BOOL;
};

不够好,因为我希望能够像这样连接字符串常量:

class A {
public:
    static const char * const STRING_PART1;
    static const char * const STRING_PART2;
    static const unsigned char BOOL;
};
const char * const A::STRING_PART1 = "PART1_";
//const char * const A::STRING_PART2 = A::STRING_PART1 + "PART2"; //obviously won't compile
//const char * const A::STRING_PART2 = strcat("PART2", A::STRING_PART1); //this is not compile-time

我也不想使用define。我想使用:

class A {
public:
    static const std::string STRING_PART1;
    static const std::string STRING_PART2;
}

它允许字符串连接并且是(AFAIK)编译时,但 std::string 在 avr 项目中不可用 - 或者我在这里错了,只是不知道如何使用它。

任何帮助表示赞赏。

【问题讨论】:

    标签: c++ avr compile-time-constant


    【解决方案1】:

    您可以继续当前使用const char* const 的想法(如果std::string 不可用)。我建议仅将#define 用于分配目的。示例:

    class A {
    public:
        static const char * const STRING_PART1;
        static const char * const STRING_PART2;
        static const unsigned char BOOL;
    };
    #define PART1_ "PART1_"  // <--- for value assignent
    #define PART2_ "PART2_"
    const char * const A::STRING_PART1 = PART1_;
    const char * const A::STRING_PART2 = PART1_ PART2_;  // <--- ok! concatenation by compiler
    

    【讨论】:

    • 感谢 iammilind,这可以编译,但是:我不想用定义污染全局命名空间(是的,我可以在初始化后取消定义它们,但恕我直言不干净),主要是第二个常量不是编译时(刚刚检查过,增加了 16 字节到整体内存使用量,不知道为什么 16)。
    • @mmm,当然第二个常量是在编译时。它会增加一些内存使用,因为你现在有 2 个字符串。 "PART1_""PART1_PART2_";第二个字符串的大小为 14 个字节。如果不是在编译时,那将是编译器错误。
    • 嗯,要么我不明白编译时常量的含义,要么你错了,但我还没有假设这一点。对我来说,编译时常量意味着它在运行时不使用任何 RAM 内存,因为它是由编译器硬编码的。即使这看起来不合逻辑,您的解决方案也会根据编译时显示的 avr-g++ 统计信息在运行时使用 RAM。它说:程序:97362 字节(74.3% 已满)数据:7660 字节(93.5% 已满),而没有第二个常量的数据少了 16 字节。第一个只增加了 2 个字节,我还不明白,假设它只是核心指针的大小。
    • @mmm,编译时间常数并不意味着它不使用内存。如果没有内存,它将存储在哪里?它必须存储在某个内存区域中,这由编译器决定。
    • 编译时间对我来说意味着它存储在 ROM(例如微控制器的闪存)中,而运行时变量存储在 RAM 中。就我而言,这是我必须备用的 RAM。编译器根据许多规则决定将变量放在哪里。定义是编译时常量的一个例子,它们显然不计入 RAM 使用量。另一个例子应该是静态类常量——但在这种情况下,我的编译器会做出不同的决定。当然,我可能会混淆。
    【解决方案2】:

    对我来说,编译时间意味着它存储在 ROM(例如微控制器的闪存)中,而运行时变量存储在 RAM 中。就我而言,这是我必须备用的 RAM。编译器根据许多规则决定将变量放在哪里。定义是编译时常量的一个例子,它们显然不计入 RAM 使用量。另一个例子应该是静态类常量——但在这种情况下,我的编译器会做出不同的决定。当然,我可能会混淆。

    我认为您实际上是在混淆事情:

    • 定义不存储在 ROM 中 - 它们根本不是程序的一部分,因为它们已经由预处理器进行评估。
    • 您所做的“编译时间”和“运行时间”之间的区别适用于评估,而不是存储。

    如果要将程序存储器(= AVR 闪存)用于常量字符串,请使用 avr/pgmspace.h 中的 PSTR 宏。

    【讨论】:

    • 通过 ROM 我的意思是定义正在被评估并转换为二进制形式,因此“存储”在编译的源代码中。所以我想我没有混淆它,只是可能不正确。我在这里想要实现的目标是以一种很好的、​​gcc 和 avrgcc 兼容的方式存储常量,而不是为此浪费 RAM。
    • 是的,#defines没有被翻译成二进制——事实上,编译器根本看不到它们,因为预处理器已经对它们求值了。如果你写“foo”,编译器看到的结果是一样的
    • &lt;avr/pgmspace.h&gt;PSTR("foo") 正是如果您的闪存比 RAM 多,您想要使用的。
    • 查看“程序空间中的数据”手册:nongnu.org/avr-libc/user-manual/pgmspace.html
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-01
    • 2016-06-28
    相关资源
    最近更新 更多