0

这个编译器业务不是我的强项...

我想<string>在我的嵌入式 c++ 代码中使用模板库。

例如(须藤代码):

#include <string>

int main() {
  std::string str = std::to_string(3.87628);
}

当我尝试编译此代码时,出现错误:

error: 'to_string' is not a member of 'std'

我的 Makefile 包含以下标志:

# compile gcc flags
ASFLAGS = $(MCU) $(AS_DEFS) $(AS_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections

CFLAGS = $(MCU) $(C_DEFS) $(C_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections

# Generate dependency information
CFLAGS += -MMD -MP -MF"$(@:%.o=%.d)"

# C++ Flags
CPPFLAGS = $(CFLAGS)
CPPFLAGS += \
-fno-exceptions \
-fno-rtti 

C_STANDARD = -std=gnu11
CPP_STANDARD += -std=gnu++14

据我了解,包含标志-std=gnu++14应该让我覆盖不?

4

2 回答 2

1

std::to_string是图书馆的一部分,而不是语言。所以-std=gnu++14如果没有在库中实现就没有效果。检查头文件是否

  • 它被宣布,并且
  • 如果它依赖于任何被定义的宏。

该库与编译器是分开的,您的工具链可能使用的是较旧的 C++ 库或针对嵌入式系统的精简库。您从哪里获取工具链以及它使用的是什么 C++ 库?标头中的版权信息可能会提供线索——包括版本信息。

std::string库在嵌入式系统中通常不合适,因为除其他问题外,它依赖于非确定性动态内存分配。

由于您的代码表明您实际上是在使用 C 字符串,而不是std::string您可能会考虑:

#include <cstdio>

int main() 
{
    char str[32] ;
    std::snprintf( str, sizeof(str), "%f", 3.87628 ) ;
}
于 2022-01-13T22:18:46.853 回答
1

C++ 在嵌入式系统中的存在是有问题的。让我们在启用了最大优化的 g++ ARM32 10.2.1 gcc none-eabi 编译器上运行您的代码-O3 -std=c++17

.LC0:
        .ascii  "%f\000"
main:
        str     lr, [sp, #-4]!
        adr     r1, .L15
        ldmia   r1, {r0-r1}
        sub     sp, sp, #36
        stm     sp, {r0-r1}
        ldr     r3, .L15+8
        add     r0, sp, #8
        mov     r2, #328
        ldr     r1, .L15+12
        bl      std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > __gnu_cxx::__to_xstring<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, char>(int (*)(char*, unsigned int, char const*, std::__va_list), unsigned int, char const*, ...)
        ldr     r0, [sp, #8]
        add     r3, sp, #16
        cmp     r0, r3
        ldrne   r1, [sp, #16]
        addne   r1, r1, #1
        blne    _ZdlPvj
        mov     r0, #0
        add     sp, sp, #36
        ldr     lr, [sp], #4
        bx      lr
.L15:
        .word   380705901
        .word   1074725535
        .word   .LC0
        .word   vsnprintf

现在这一切都肿了!?我是不是忘记了-O3flag,呵呵,不,我没有……你发布的程序没有副作用。或者我们认为 - 我们一直是 cplusplus:ed。我本来期望一个行为正确的编译-O3.

所以问题显然不是如何std::string在项目中使用,答案也不是“在 C++2x 中你没有使用 constexpr,这不是你编写现代 C++ blahblah 的方式”。问题是,一旦某些 PC 程序员将这个完全不可接受的代码拖到您的微控制器中,只是因为有人决定允许 C++,如何挽救该项目。答案如下:

  • 第 1 步:切换到 C。相同的编译器 ARM32 10.2.1 gcc none-eabi。

  • 第 2 步:当不需要它们时,不要将时间浪费在臃肿的课程上。一个简单的事情,例如将浮点常量转换为字符串,可以而且应该在预处理器中完成。任何中级 C 或 C++ 程序员都应该了解字符串化宏:

    #define S(x) #x
    #define STR(x) S(x)
    
  • 第三步:测试。一个简单的测试程序-ffreestanding和一些副作用,以确保字符串不会被优化,例如:

      #include <stdio.h>
      #define S(x) #x
      #define STR(x) S(x)
    
      void main (void)
      {
        char str[] = STR(3.87628);
    
        puts(str); // just to introduce a side effect
      }
    

生成的机器代码的相关部分现在是这样的:

.LC0:
        .ascii  "3.87628\000"
main:
        str     lr, [sp, #-4]!
        sub     sp, sp, #12
        mov     r3, sp
        ldr     r2, .L4
        ldm     r2, {r0, r1}
        stm     r3, {r0, r1}
.L4:
        .word   .LC0

这段代码很好。我们可以继续编写我们的应用程序。

于 2022-01-14T15:46:17.163 回答