嵌入式控制器中 C++ 的用處真的比 C 大嗎?

同學說 C++ 能更好的完成單片機的編程。請問確實如此嗎?比如 arm、dsp中。


不知道題主說的嵌入式控制器具體是什麼東西,我做嵌入式好多年都沒聽說這個說法,具體是哪種控制器?

如果指的是嵌入式開發,目前來看,主要以C為主,越靠近底層,用的C越多。有一些靠近上層的應用可能是用C++寫的,主力還是C語言

為什麼用C不用C++?原因是C的SDK好寫,兼容性好,尤其是以二進位格式發布的SDK。

比如,SDK里有函數名vmTrans,如果用C編譯器去編譯生成的庫,二進位庫里,這個函數的名字還是vmTrans,不管你用什麼編譯器去編譯,生成的函數名基本上跟vmTrans一樣,如果有差別,也不是很大。但如果用C++的編譯器去生成庫,那麼名字可不一定是什麼呢。

靜態的函數還好說,如果C++里包含虛函數之類的東西,那麼生成的二進位名字就沒法看了,而且換一個編譯器肯定完蛋。咱們還不算不同標準的C++的差異性呢。

現在硬體廠商的保密性還是很強的,並不是所有廠商都願意開放SDK的源碼,如果發布二進位的庫,最好的選擇就是C,鏈接的時候基本沒問題。如果使用C++,那麼用戶要想使用這個SDK,必須用跟廠商一樣的編譯器,這對於用戶來說並不方便。用戶可能是在Windows平台上開發,也可能是在Linux平台上開發,甚至可能是在MacOS上開發,廠商如果自己提供的編譯器用不了,那麼別的編譯器要想正確鏈接C++的庫並不容易。

所以嵌入式開發里,提供C++SDK的嵌入式廠商,要麼是給了源碼,要麼是限定某幾個特定的編譯器。而C語言由於較好的兼容性,還是普遍被大多數嵌入式廠商使用的,因為C寫的SDK,不管你是用gcc還是armcc或者別的什麼東西,基本上不會鏈出問題。

對於我自己來說,每次C++更新標準,感覺都加了很多東西,換個編譯器C++編譯出來的東西可能就不一樣。相反C標準的步伐還是很慢的,慢的一個好處就是兼容性好。

可能有人不太明白這個兼容性的問題,我舉一個很實際的例子:

代碼:

void * vmTrans(void * addr)
{
void * ret;
ret = (void *)(((unsigned int) addr) | 0x80000000);

return ret;
}

使用g++編譯成一個.o文件,使用objdump查看:

lb.o: file format elf32-i386

Disassembly of section .text:

00000000 &<_Z7vmTransPv&>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 ec 10 sub $0x10,%esp
6: 8b 45 08 mov 0x8(%ebp),%eax
9: 0d 00 00 00 80 or $0x80000000,%eax
e: 89 45 fc mov %eax,-0x4(%ebp)
11: 8b 45 fc mov -0x4(%ebp),%eax
14: c9 leave
15: c3 ret

符號名是_Z7vmTransPv,這名字大概還可以接受一下。

再用VS2008編譯同樣的代碼,objdump一下:

/mnt/hgfs/D/vmtest.obj: file format pe-i386

Disassembly of section .text:

00000000 &:
0: 55 push %ebp
1: 8b ec mov %esp,%ebp
3: 81 ec cc 00 00 00 sub $0xcc,%esp
9: 53 push %ebx
a: 56 push %esi
b: 57 push %edi
c: 8d bd 34 ff ff ff lea -0xcc(%ebp),%edi
12: b9 33 00 00 00 mov $0x33,%ecx
17: b8 cc cc cc cc mov $0xcccccccc,%eax
1c: f3 ab rep stos %eax,%es:(%edi)
1e: 8b 45 08 mov 0x8(%ebp),%eax
21: 0d 00 00 00 80 or $0x80000000,%eax
26: 89 45 f8 mov %eax,-0x8(%ebp)
29: 8b 45 f8 mov -0x8(%ebp),%eax
2c: 5f pop %edi
2d: 5e pop %esi
2e: 5b pop %ebx
2f: 8b e5 mov %ebp,%esp
31: 5d pop %ebp
32: c3 ret

誰能告訴我那個詭異的符號(?vmTrans@@YAPAXPAX@Z)是什麼東西?

如果全使用c格式編譯:

lb1.o: file format elf32-i386

Disassembly of section .text:

00000000 &:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 ec 10 sub $0x10,%esp
6: 8b 45 08 mov 0x8(%ebp),%eax
9: 0d 00 00 00 80 or $0x80000000,%eax
e: 89 45 fc mov %eax,-0x4(%ebp)
11: 8b 45 fc mov -0x4(%ebp),%eax
14: c9 leave
15: c3 ret

符號名和源文件一樣。

再看VC:

/mnt/hgfs/D/v2.obj: file format pe-i386

Disassembly of section .text:

00000000 &<_vmTrans&>:
0: 55 push %ebp
1: 8b ec mov %esp,%ebp
3: 81 ec cc 00 00 00 sub $0xcc,%esp
9: 53 push %ebx
a: 56 push %esi
b: 57 push %edi
c: 8d bd 34 ff ff ff lea -0xcc(%ebp),%edi
12: b9 33 00 00 00 mov $0x33,%ecx
17: b8 cc cc cc cc mov $0xcccccccc,%eax
1c: f3 ab rep stos %eax,%es:(%edi)
1e: 8b 45 08 mov 0x8(%ebp),%eax
21: 0d 00 00 00 80 or $0x80000000,%eax
26: 89 45 f8 mov %eax,-0x8(%ebp)
29: 8b 45 f8 mov -0x8(%ebp),%eax
2c: 5f pop %edi
2d: 5e pop %esi
2e: 5b pop %ebx
2f: 8b e5 mov %ebp,%esp
31: 5d pop %ebp
32: c3 ret

名字前多了一個下劃線,但名字是對的(這個下劃線可以用編譯選項去掉)。

所以,如果做SDK,使用C語言還是比較好的。


是的 能更好,有幸能接觸一個broadcom的sdk就是,但不是純的,有不少c代碼。

用的是armcc GCC 編譯。m0內核。

我想廠家不用c++多是因為

1客戶程序員多是「精通」c,c++他們屬於豬一樣隊友

2各種單片機編譯調試環境c生態更成熟。

說到底原廠尋求的是最適合產品的語言而不是最適合功能性能的語言。


C++那杯具的ABI兼容性,真的大丈夫嗎?


雖然我覺得如果能用c++的話,簡單的基於對象加泛形,多用模版元玩靜態抽象加靜態多態,注意代碼膨脹,少用宏的stl風格可以比c語言爽不少,但是我到現在暫時還沒在哪個單片機上見到過c++的編譯器。。


apm飛控的代碼是用c++寫的,但是通常c寫嵌入式程序比較多。


學習


MCU編程,沒見過用C++的,都是C


用的是 C with class. 現代化的C++應該沒有.


我也沒用過cpp寫微控制器程序


推薦閱讀:

如何通俗地講清 I2C、SPI、USB、UART、RS232 到底是什麼東西?
為什麼英偉達Tegra X1晶元不採用丹佛架構?
為什麼windows和intel結成了這麼牢固的聯盟?
可以使用USB2.0介面進行全雙工通訊么,雙方都可以主動發送么?

TAG:ARM | C編程語言 | C | DSP數字信號處理 |