簡體   English   中英

為什么我不能將 std::string 與 arm-none-eabi-g++ 編譯器一起使用?

[英]Why can I not use std::string with the arm-none-eabi-g++ compiler?

這個編譯器業務不是我的強項...

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

例如(須藤代碼):

#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應該讓我不知道嗎?

std::to_string是庫的一部分,而不是語言。 所以-std=gnu++14如果沒有在庫中實現就沒有效果。 檢查 header 文件看是否

  • 它被宣布,並且
  • 如果它依賴於任何被定義的宏。

您提供的代碼也是胡說八道。 它應該是:

std::string str = std::to_string(3.87628);

但這不會解決你的問題。

該庫與編譯器分開,您的工具鏈可能使用的是較舊的 C++ 庫或針對嵌入式系統的精簡庫。 您從哪里獲得工具鏈以及它使用的是什么 C++ 庫? header 中的版權信息可能會提供一個線索——包括版本信息。

std::string庫在嵌入式系統中通常不合適,因為除其他問題外,它依賴於非確定性動態 memory 分配。

由於您的代碼表明您實際上使用的是 C 字符串而不是std::string您可能會考慮:

#include <cstdio>

int main() 
{
    char str[32] ;
    std::snprintf( str, sizeof(str), "%f", 3.87628 ) ;
}

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

現在這一切都腫了嗎?? 我是不是忘記了-O3標志,呵呵,不,我沒有……您發布的程序沒有副作用。 或者我們認為 - 我們一直是 cplusplus:ed。 我本來希望一個行為正確的編譯器在-O3下不生成任何代碼

所以問題顯然不是如何在項目中使用std::string ,答案也不是“在 C++2x 中,你沒有使用 constexpr 這不是你編寫現代 C++ blahblah 的方式”。 問題是,一旦某些 PC 程序員將這個完全不可接受的代碼拖到您的微控制器中,只是因為有人決定允許 C++,如何挽救該項目。 答案如下:

  • 第一步:切換到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

這段代碼很好。 我們可以繼續編寫我們的應用程序。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM