keil可以使用c++编程吗?
keil如何使用C++编程,及C++11以上如何更换库文件以支持C++新特性
目录
因为本人最开始是学习c++/Linux路线的,对于keil教学中全部都是c语言很难容忍。于是尝试在keil中使用c++进行编程,发现其实keil和其他IDE是类似的,都是可以支持c++编程的。
一、编译器为什么支持C/C++混合编程
如果你曾浏览过ST官方提供的标准库,你或许会发现他们都有一个共同点---都包含了extern"C"语句。
#ifdef __cplusplus
extern "C"
{
#endif
//C++的代码
#ifdef __cplusplus
}
#endif

在C++中,函数和变量的名称会被“名称修饰”,这是为了支持函数重载、类成员函数等特性。例如,一个C++函数
void foo(int, double)在编译后可能被修饰为_Z3fooid(具体修饰规则因编译器而异)。而C语言不支持名称修饰,其函数名保持原样(如foo)。当C++代码需要调用C语言的库函数时,编译器无法直接匹配修饰后的名称,导致链接错误。
extern "C"的作用是告诉编译器禁用名称修饰,使C++代码中的函数声明与C语言的名称保持一致,从而实现混合编程。
所以当我们用extern"C"包裹一段代码的时候,他就会按照c语言的规则进行编译成.o文件,然后经过链接器链接就成了可执行程序,从而实现c/c++混合编程。
二、简单实现一个LED类
注意源文件要改成.cpp后缀

#pragma once
#include "stm32f10x.h" // Device header
class LED_Class
{
private:
GPIO_TypeDef *GPIOx;
uint16_t GPIO_Pin;
uint32_t RCC_APB2Periph;
public:
LED_Class(GPIO_TypeDef *GPIOx,uint16_t GPIO_Pin, uint32_t RCC_APB2Periph)
{
LED_Class::GPIOx = GPIOx;
LED_Class::GPIO_Pin = GPIO_Pin;
LED_Class::RCC_APB2Periph = RCC_APB2Periph;
}
void Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph, ENABLE);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOx, &GPIO_InitStruct);
}
void Open(void)
{
GPIO_SetBits(GPIOx, GPIO_Pin);
}
void Close(void)
{
GPIO_ResetBits(GPIOx, GPIO_Pin);
}
};
int main(void)
{
LED_Class LED1(GPIOC, GPIO_Pin_13, RCC_APB2Periph_GPIOC);
// LED_Class LED2(GPIOC, GPIO_Pin_13, RCC_APB2Periph_GPIOC);
LED1.Init();
// LED2.Init();
while(1)
{
LED1.Open();
// LED1.Close();
}
}
三、c++编写代码的优缺点
优点:
面向对象编程特性
C++支持面向对象编程(OOP),包括封装、继承和多态等特性。这些特性有助于提高代码的可重用性、可维护性和扩展性,尤其适合开发复杂系统。标准库支持
C++拥有丰富的标准模板库(STL),提供了大量高效的数据结构和算法,如向量、列表、映射等。这些工具可以简化开发过程,减少重复代码的编写。类型安全
C++通过强类型检查和模板元编程,提供了更高的类型安全性,减少了因类型不匹配导致的运行时错误。性能优化
C++允许开发者直接管理内存和硬件资源,同时通过内联函数、模板优化等技术,生成高效的机器代码,满足实时性要求较高的应用场景。跨平台兼容性
C++代码具有良好的可移植性,可以在不同架构的单片机上编译运行,只需少量修改即可适配新平台。坏处:
资源消耗较大
C++的运行时环境(如异常处理、RTTI)和标准库会占用较多的内存和存储空间,这对资源受限的单片机(如8位或16位MCU)来说可能难以承受。代码体积较大
由于C++支持丰富的特性和模板元编程,生成的二进制代码通常比C语言更大,可能导致Flash存储空间不足。实时性挑战
C++的动态内存分配、异常处理等特性可能导致不可预测的执行时间,影响实时系统的性能。例如,new和delete操作可能引发内存碎片化,增加延迟。学习曲线陡峭
C++的语法和概念(如指针、模板、智能指针)较为复杂,对初学者来说学习成本较高,尤其需要掌握内存管理和资源释放等细节。工具链支持不足
相比C语言,C++在单片机开发领域的工具链(如编译器、调试器)支持不够成熟,部分编译器可能对C++特性的支持有限。生态系统不完善
C++在单片机领域的第三方库和框架较少,开发者可能需要自行实现底层功能,增加了开发难度和时间成本。
早期无人使用的原因:
硬件资源限制
早期单片机(如8051、AVR)的Flash和RAM容量非常有限(通常为几KB到几十KB),而C++的运行时环境和标准库需要较大的资源开销,难以在这些平台上运行。实时性要求
单片机通常用于实时控制系统(如工业自动化、汽车电子),对执行时间的确定性要求极高。C++的动态内存分配和异常处理可能引入不可预测的延迟,不适合此类应用。工具链不成熟
早期编译器对C++的支持不完善,缺乏针对单片机的优化,导致生成的代码效率低下,甚至无法编译通过。开发习惯和成本
C语言在单片机领域已有成熟的生态系统和开发习惯,开发者更倾向于使用熟悉的工具和语言,迁移到C++的成本较高。现在逐步推广的原因:
硬件性能提升
现代单片机(如ARM Cortex-M系列、ESP32)的Flash和RAM容量大幅提升(可达数百KB到几MB),性能足以支持C++的运行时环境和标准库。实时操作系统(RTOS)普及
RTOS(如FreeRTOS、ThreadX)的广泛应用降低了实时性开发的难度,开发者可以通过RTOS管理任务调度和资源分配,减少C++对实时性的影响。工具链和库的完善
现代编译器(如GCC、ARMCC)对C++的支持更加完善,提供了针对单片机的优化选项。同时,第三方库(如Arduino C++库、mbed OS)的出现降低了开发门槛。复杂系统需求增加
随着物联网(IoT)和嵌入式系统的发展,单片机应用越来越复杂,需要支持网络通信、图形界面、多线程等功能。C++的面向对象特性和标准库能够更好地满足这些需求。开发者技能提升
现代开发者普遍具备C++编程能力,能够快速上手单片机开发。同时,C++的教育资源丰富,降低了学习成本。
四、关于ARMCompiler 以及C++11
ARM Compiler 是 ARM 公司专门为基于 ARM 架构的处理器设计的高效编译工具链,广泛应用于嵌入式系统、移动设备等领域。它能够将 C、C++ 等源代码编译为 ARM 处理器可执行的二进制代码,并针对 ARM 架构进行深度优化,以提升性能、降低功耗和代码体积。
在c++98之前的版本都可以直接使用version 5编译链进行c++编程。
不过缺陷是只能只用C98以前的c++语法,因为老版本的keil_v5的库匹配的就是C98,如果你想强行使用C++11之后的新语法,会出现报错


(1)库文件替换
如何更新库文件
想使用version 6版本的ARM编译链,以及c++11及以上的特性,这样的操作是远远不够的,还需要把整个的工程目录树下的库文件全部替换成最新版的。这个操作和上一篇文章创建一个工程类似。
首先你需要到官网下载这两个文件,他们是较为新的版本的库
然后在你的工程文件中依次替换,替换完成后应该是这样子的。



注意:因为你把库文件给替换了,所以需要进入keil的工作组中重新把新的文件加入进来,把原来的替换掉。
(2)RTE
"RTE_Components.h"这个文件是用来管理外设模块是否包含的文件。就好像
当你正确的完成了上面的步骤会发现这里报错了,只需要进入stm32f10x_conf.h文件中把"#include "RTE_Components.h"注释掉即可。

从此你就发现你可以使用C++14的新特性啦。

五、总结
虽然在以前的嵌入式开发中C++使用的比较少,但是随着单片机资源的提升,今后C++开发会成为主流。但是c++的很多高级特性仍然需要大量的空间,并不适合嵌入式资源使用,比如模板、异常等,所以在使用c++进行嵌入式开发的时候仍需要尽量减少内存等资源被C++库的占用。
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐





所有评论(0)