[英]Why can I not use std::string with the arm-none-eabi-g++ compiler?
This compiler business is not my forte...这个编译器业务不是我的强项...
I want to use the <string>
template library in my embedded c++ code.我想在我的嵌入式 c++ 代码中使用
<string>
模板库。
For example (sudo code):例如(须藤代码):
#include <string>
int main() {
std::string str = std::to_string(3.87628);
}
When I try to compile this code, I get the error:当我尝试编译此代码时,出现错误:
error: 'to_string' is not a member of 'std'
My Makefile contains the following flags:我的 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
To my understanding, the inclusion of flag -std=gnu++14
should have me covered no?据我了解,包含标志
-std=gnu++14
应该让我不知道吗?
std::to_string
is part of the library, not the language. std::to_string
是库的一部分,而不是语言。 So -std=gnu++14
will have no effect if it is not implemented in the library.所以
-std=gnu++14
如果没有在库中实现就没有效果。 Check the header file to see if检查 header 文件看是否
The code you presented is also nonsense.您提供的代码也是胡说八道。 It should be:
它应该是:
std::string str = std::to_string(3.87628);
but that won't solve your problem.但这不会解决你的问题。
The library is separate from the compiler, and your toolchain may be using an older C++ library or a cut-down library aimed at embedded systems.该库与编译器分开,您的工具链可能使用的是较旧的 C++ 库或针对嵌入式系统的精简库。 From where did your source the toolchain and what C++ library is it using?
您从哪里获得工具链以及它使用的是什么 C++ 库? The copyright message in the header may provide a clue - including version information.
header 中的版权信息可能会提供一个线索——包括版本信息。
The std::string
library is often inappropriate in embedded systems because amongst other issues it relies on non-deterministic dynamic memory allocation. std::string
库在嵌入式系统中通常不合适,因为除其他问题外,它依赖于非确定性动态 memory 分配。
Since your code suggests you are actually using C strings rather than std::string
you might consider:由于您的代码表明您实际上使用的是 C 字符串而不是
std::string
您可能会考虑:
#include <cstdio>
int main()
{
char str[32] ;
std::snprintf( str, sizeof(str), "%f", 3.87628 ) ;
}
The presence of C++ in embedded systems is problematic. C++ 在嵌入式系统中的存在是有问题的。 Lets run your code on an g++ ARM32 10.2.1 gcc none-eabi compiler with maximum optimizations
-O3 -std=c++17
enabled:让我们在 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
Now wth is all this bloat??现在这一切都肿了吗?? Did I forget the
-O3
flag, huh, no I didn't... The program you posted has no side effects.我是不是忘记了
-O3
标志,呵呵,不,我没有……您发布的程序没有副作用。 Or so we thought - we've been cplusplus:ed.或者我们认为 - 我们一直是 cplusplus:ed。 I would have expected a correctly behaving compiler to generate no code under
-O3
.我本来希望一个行为正确的编译器在
-O3
下不生成任何代码。
So the question is clearly not how to use std::string
in the project and the answer isn't "In C++2x you didn't use constexpr this is not how you write modern C++ blahblah".所以问题显然不是如何在项目中使用
std::string
,答案也不是“在 C++2x 中,你没有使用 constexpr 这不是你编写现代 C++ blahblah 的方式”。 The question is rather how to salvage the project once some PC programmer did drag this completely unacceptable code into your microcontroller just because someone decided to allow C++.问题是,一旦某些 PC 程序员将这个完全不可接受的代码拖到您的微控制器中,只是因为有人决定允许 C++,如何挽救该项目。 The answer to that follows:
答案如下:
Step 1: switch to C.第一步:切换到C。 Same compiler ARM32 10.2.1 gcc none-eabi.
相同的编译器 ARM32 10.2.1 gcc none-eabi。
Step 2: don't waste time on bloat classes when there is no need for them.第 2 步:当不需要它们时,不要将时间浪费在臃肿的课程上。 A simple thing such as converting a float constant to a string can and should be done in the pre-processor.
一个简单的事情,例如将浮点常量转换为字符串,可以而且应该在预处理器中完成。 Any intermediate-level C or C++ programmer ought to know about stringification macros:
任何中级 C 或 C++ 程序员都应该了解字符串化宏:
#define S(x) #x #define STR(x) S(x)
Step 3: test.第三步:测试。 A simple test program with
-ffreestanding
and some side-effect to ensure that the string doesn't get optimized out, for example:一个简单的测试程序,带有
-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 }
The relevant parts of the resulting machine code is now something like this:生成的机器代码的相关部分现在是这样的:
.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
This code is fine.这段代码很好。 We can get on with writing our application.
我们可以继续编写我们的应用程序。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.