Domanda

Domanda

Ho due compilatori sul mio hardware C ++ e C89

Sto pensando di usare C ++ con le classi ma senza polimorfismo (per evitare vtables). I motivi principali per cui mi piacerebbe usare il C ++ sono:

  • Preferisco usare & # 8220; inline & # 8221; funzioni anziché definizioni macro.
  • Mi piacerebbe usare gli spazi dei nomi poiché i prefissi ingombrano il codice.
  • Vedo C ++ un po 'più sicuro soprattutto a causa dei modelli e del casting dettagliato.
  • Mi piacciono molto le funzioni e i costruttori sovraccarichi (usati per il casting automatico).

Vedi qualche motivo per restare con C89 durante lo sviluppo di hardware molto limitato (4kb di RAM)?

Conclusione

Grazie per le tue risposte, sono state davvero utili!

Ho riflettuto sull'argomento e rimarrò con C principalmente perché:

  1. È più facile prevedere il codice effettivo in C e questo è molto importante se si hanno solo 4kb di RAM.
  2. Il mio team è composto principalmente da sviluppatori C, quindi le funzionalità C ++ avanzate non verranno utilizzate di frequente.
  3. Ho trovato un modo per incorporare le funzioni nel mio compilatore C (C89).

È difficile accettare una risposta dato che hai fornito così tante buone risposte. Sfortunatamente non posso creare un wiki e accettarlo, quindi sceglierò una risposta che mi ha fatto pensare di più.

È stato utile?

Soluzione

Due motivi per usare C su C ++:

  1. Per molti processori embedded, o non esiste un compilatore C ++ o devi pagare un extra per questo.
  2. La mia esperienza è che una percentuale significativa di ingegneri del software embedded ha poca o nessuna esperienza di C ++ - o a causa di (1), o perché tende a non essere insegnata a gradi di ingegneria elettronica - e quindi sarebbe meglio attenersi a ciò che sanno.

Inoltre, la domanda originale e una serie di commenti menzionano i 4 KB di RAM . Per un tipico processore incorporato, la quantità di RAM è (principalmente) non correlata alla dimensione del codice, poiché il codice viene archiviato ed eseguito da, flash.

Certamente, la quantità di spazio di archiviazione del codice è qualcosa da tenere a mente, ma poiché nuovi processori, più capienti, appaiono sul mercato, è meno un problema di quanto non fosse per tutti tranne i progetti più sensibili ai costi .

Sull'uso di un sottoinsieme di C ++ da utilizzare con sistemi embedded: ora esiste un MISRA C ++ standard, che può valere la pena dare un'occhiata.

MODIFICA: Vedi anche questa domanda , che ha portato a un dibattito su C vs C ++ per incorporato sistemi.

Altri suggerimenti

Per un target molto limitato di risorse come 4KB di RAM, testerei le acque con alcuni campioni prima di impegnarmi molto che non può essere facilmente riportato in un ANSI C puro implementazione.

Il gruppo di lavoro Embedded C ++ ha proposto un sottoinsieme standard del linguaggio e un sottoinsieme standard della libreria standard da seguire. Purtroppo ho perso la traccia di quello sforzo quando è morto il Journal of C User. Sembra che ci sia un articolo su Wikipedia e che comitato esiste ancora.

In un ambiente incorporato, devi davvero stare attento all'allocazione della memoria. Per far valere tale cura, potrebbe essere necessario definire l'operatore globale new () e i suoi amici in qualcosa che non può nemmeno essere collegato in modo da sapere che non viene utilizzato. Il posizionamento nuovo d'altra parte è probabilmente il tuo amico, se usato con giudizio insieme a uno schema di allocazione stabile, sicuro per i thread e garantito dalla latenza.

Le funzioni incorporate non causeranno molti problemi, a meno che non siano abbastanza grandi da dover essere vere funzioni in primo luogo. Naturalmente le macro che hanno sostituito hanno avuto lo stesso problema.

Anche i modelli potrebbero non causare un problema a meno che la loro istanza non sia corretta. Per qualsiasi modello che usi, controlla il tuo codice generato (la mappa dei collegamenti potrebbe avere indizi sufficienti) per accertarti che siano avvenute solo le istanze che intendevi utilizzare.

Un altro problema che potrebbe sorgere è la compatibilità con il debugger. Non è insolito che un debugger hardware altrimenti utilizzabile abbia un supporto molto limitato per l'interazione con il codice sorgente originale. Se è necessario eseguire correttamente il debug in assembly, l'interessante modifica del nome di C ++ può aggiungere ulteriore confusione all'attività.

RTTI, cast dinamici, ereditarietà multipla, polimorfismo pesante ed eccezioni comportano tutti una certa quantità di costi di runtime per il loro uso. Alcune di quelle funzionalità che costano sull'intero programma se vengono utilizzate, altre aumentano semplicemente il peso delle classi che ne hanno bisogno. Conoscere la differenza e scegliere saggiamente funzionalità avanzate con la piena conoscenza di almeno un'analisi costi / benefici superficiale.

In un piccolo ambiente incorporato si collegherà direttamente a un kernel in tempo reale o si eseguirà direttamente sull'hardware. Ad ogni modo, dovrai assicurarti che il tuo codice di avvio di runtime gestisca correttamente le faccende di avvio specifiche di C ++. Questo potrebbe essere semplice come assicurarsi di utilizzare le giuste opzioni di linker, ma poiché è comune avere il controllo diretto sulla sorgente al punto di ingresso del reset di accensione, potrebbe essere necessario verificarlo per assicurarsi che faccia tutto. Ad esempio, su una piattaforma ColdFire su cui ho lavorato, gli strumenti di sviluppo sono stati forniti con un modulo CRT0.S che presentava gli inizializzatori C ++ ma commentava. Se l'avessi usato direttamente dalla scatola, sarei stato confuso da oggetti globali i cui costruttori non erano mai stati eseguiti.

Inoltre, in un ambiente incorporato, è spesso necessario inizializzare i dispositivi hardware prima che possano essere utilizzati e, se non ci sono sistemi operativi e caricatori di avvio, è il tuo codice a farlo. Dovrai ricordare che i costruttori per gli oggetti globali vengono eseguiti prima di main () , quindi dovrai modificare il tuo CRT0.S locale (o suo equivalente) per ottenere l'inizializzazione dell'hardware eseguita prima vengono chiamati i costruttori globali stessi. Ovviamente, la parte superiore di main () è troppo tardi.

No. Qualsiasi funzionalità del linguaggio C ++ che potrebbe causare problemi (polimorfismo di runtime, RTTI, ecc.) Può essere evitata durante lo sviluppo incorporato. Esiste una comunità di sviluppatori C ++ incorporati (ricordo di aver letto le colonne degli sviluppatori incorporati utilizzando C ++ nel vecchio diario degli utenti C / C ++) e non riesco a immaginare che sarebbero molto vocali se la scelta fosse così male.

Il Rapporto tecnico sulle prestazioni C ++ è un ottima guida per questo genere di cose. Si noti che ha una sezione sulle preoccupazioni relative alla programmazione integrata!

Inoltre, ++ sulla menzione di Embedded C ++ nelle risposte. Lo standard non è al 100% per i miei gusti, ma è un buon riferimento quando si decide quali parti del C ++ potrebbero essere eliminate.

Durante la programmazione per piccole piattaforme, disabilitiamo le eccezioni e RTTI, evitiamo l'eredità virtuale e prestiamo molta attenzione al numero di funzioni virtuali che abbiamo in giro.

Il tuo amico è la mappa del linker: controlla spesso e vedrai rapidamente sorgenti di codice e memoria statica gonfiarsi.

Dopodiché, si applicano le considerazioni standard sull'uso della memoria dinamica: in un ambiente limitato come quello che menzioni, potresti non voler usare affatto le allocazioni dinamiche. A volte puoi cavartela con pool di memoria per piccoli alloc dinamici o "quotazioni basate su frame" allocazione in cui preallocate un blocco e buttate via tutto in seguito.

Raccomando di usare il compilatore C ++, ma limitando l'uso delle funzionalità specifiche di C ++. Puoi programmare come C in C ++ (il runtime C è incluso quando esegui C ++, sebbene nella maggior parte delle applicazioni integrate non usi comunque la libreria standard).

Puoi andare avanti e usare le classi C ++ ecc., solo

  • Limita il tuo utilizzo delle funzioni virtuali (come hai detto)
  • Limita l'utilizzo dei modelli
  • Per una piattaforma integrata, ti consigliamo di sostituire l'operatore nuovo e / o utilizzare il posizionamento nuovo per l'allocazione della memoria.

In qualità di firmware / ingegnere di sistemi embedded, posso dirvi alcuni dei motivi per cui C è ancora la scelta n. 1 su C ++ e sì, sono fluente in entrambi.

1) Alcuni target su cui sviluppiamo hanno 64kB di RAM sia per il codice che per i dati, quindi devi assicurarti che ogni conteggio dei byte, e sì, mi sono occupato dell'ottimizzazione del codice per salvare 4 byte che mi costano 2 ore, e quello è nel 2008.

2) Ogni funzione della libreria C viene esaminata prima di essere lasciata nel codice finale, a causa della limitazione delle dimensioni, quindi preferiamo che le persone non utilizzino divide (nessun divisore hardware, quindi è necessaria una grande libreria), malloc (perché noi non hanno heap, tutta la memoria è allocata dal buffer di dati in blocchi di 512 byte e deve essere revisionata dal codice) o altra pratica orientata agli oggetti che comporta una grande penalità. Ricorda, ogni funzione di libreria che usi conta.

3) Hai mai sentito parlare del termine overlay? hai così poco spazio nel codice che a volte devi scambiare le cose con un altro set di codice. Se si chiama una funzione di libreria, la funzione di libreria deve essere residente. Se lo usi solo in una funzione overlay, stai sprecando molto spazio facendo affidamento su troppi metodi orientati agli oggetti. Quindi, non assumere alcuna funzione di libreria C, per non parlare del C ++ da accettare.

4) La fusione e persino l'imballaggio (laddove la struttura dei dati non allineata oltrepassa i confini delle parole) sono necessari a causa della progettazione hardware limitata (ovvero un motore ECC collegato in un determinato modo) o per far fronte a un bug hardware. Non puoi assumere troppo in modo implicito, quindi perché l'oggetto lo orienta troppo?

5) Scenario peggiore: l'eliminazione di alcuni dei metodi orientati agli oggetti costringerà lo sviluppo a pensare prima di utilizzare risorse che possono esplodere (ovvero allocando 512 byte su uno stack anziché da un buffer di dati) e prevenire alcuni dei potenziali peggiori scenario del caso che non è stato testato per o elimina l'intero percorso del codice tutti insieme.

6) Usiamo molta astrazione per mantenere l'hardware dal software e rendere il codice il più portatile possibile e la simulazione amichevole. L'accesso all'hardware deve essere racchiuso in una funzione macro o incorporata che viene compilata in modo condizionale tra piattaforme diverse, il tipo di dati deve essere trasmesso come dimensione in byte anziché come destinazione specifica, non è consentito l'utilizzo del puntatore diretto (poiché alcune piattaforme presuppongono che l'I / O mappato in memoria sia il uguale alla memoria dati), ecc.

Posso pensare di più, ma tu hai l'idea. Noi ragazzi del firmware abbiamo una formazione orientata agli oggetti, ma il compito del sistema incorporato può essere così orientato all'hardware e di basso livello, che non è di alto livello o estraibile per natura.

A proposito, ogni lavoro di firmware a cui ho partecipato utilizza il controllo del codice sorgente, non so da dove provenga quell'idea.

-qualcuno del firmware di SanDisk.

  

La mia preferenza personale è C perché:

     
      
  • So cosa sta facendo ogni riga di codice (e costi)
  •   
  • Non conosco C ++ abbastanza bene da sapere cosa sta facendo (e costa) ogni riga di codice
  •   

Perché la gente dice questo? non sai cosa sta facendo ogni linea di C se non controlli l'output asm. Lo stesso vale per C ++.

Ad esempio, che cosa produce questa dichiarazione innocente:

a[i] = b[j] * c[k];

Sembra abbastanza innocente, ma un compilatore basato su gcc produce questo asm per un micro a 8 bit

CLRF 0x1f, ACCESS
RLCF 0xfdb, W, ACCESS
ANDLW 0xfe
RLCF 0x1f, F, ACCESS
MOVWF 0x1e, ACCESS
MOVLW 0xf9
MOVF 0xfdb, W, ACCESS
ADDWF 0x1e, W, ACCESS
MOVWF 0xfe9, ACCESS
MOVLW 0xfa
MOVF 0xfdb, W, ACCESS
ADDWFC 0x1f, W, ACCESS
MOVWF 0xfea, ACCESS
MOVFF 0xfee, 0x1c
NOP
MOVFF 0xfef, 0x1d
NOP
MOVLW 0x1
CLRF 0x1b, ACCESS
RLCF 0xfdb, W, ACCESS
ANDLW 0xfe
RLCF 0x1b, F, ACCESS
MOVWF 0x1a, ACCESS
MOVLW 0xfb
MOVF 0xfdb, W, ACCESS
ADDWF 0x1a, W, ACCESS
MOVWF 0xfe9, ACCESS
MOVLW 0xfc
MOVF 0xfdb, W, ACCESS
ADDWFC 0x1b, W, ACCESS
MOVWF 0xfea, ACCESS
MOVFF 0xfee, 0x18
NOP
MOVFF 0xfef, 0x19
NOP
MOVFF 0x18, 0x8
NOP
MOVFF 0x19, 0x9
NOP
MOVFF 0x1c, 0xd
NOP
MOVFF 0x1d, 0xe
NOP
CALL 0x2142, 0
NOP
MOVFF 0x6, 0x16
NOP
MOVFF 0x7, 0x17
NOP
CLRF 0x15, ACCESS
RLCF 0xfdf, W, ACCESS
ANDLW 0xfe
RLCF 0x15, F, ACCESS
MOVWF 0x14, ACCESS
MOVLW 0xfd
MOVF 0xfdb, W, ACCESS
ADDWF 0x14, W, ACCESS
MOVWF 0xfe9, ACCESS
MOVLW 0xfe
MOVF 0xfdb, W, ACCESS
ADDWFC 0x15, W, ACCESS
MOVWF 0xfea, ACCESS
MOVFF 0x16, 0xfee
NOP
MOVFF 0x17, 0xfed
NOP

Il numero di istruzioni prodotte dipende enormemente da:

  • Le dimensioni di a, b e c.
  • se tali puntatori sono memorizzati nello stack o sono globali
  • se i, j e k sono nello stack o sono globali

Questo è particolarmente vero nel minuscolo mondo embedded, in cui i processori non sono configurati per gestire C. Quindi la mia risposta sarebbe che C e C ++ sono uguali tra loro, a meno che non si esamini sempre l'output asm, in in tal caso sono altrettanto buoni l'uno dell'altro.

Hugo

Ho sentito che alcune persone preferiscono il C per il lavoro incorporato a causa del fatto che è più semplice e quindi più facile prevedere il codice reale che verrà generato.

Personalmente penso che scrivere C ++ in stile C (usando i template per la sicurezza dei tipi) ti darebbe molti vantaggi e non vedo alcun motivo reale per non farlo.

Non vedo alcun motivo per usare C invece di C ++. Qualunque cosa tu possa fare in C, puoi farlo anche in C ++. Se si desidera evitare spese generali di VMT, non utilizzare metodi virtuali e polimorfismo.

Tuttavia, C ++ può fornire alcuni modi di dire molto utili senza spese generali. Uno dei miei preferiti è RAII. Le lezioni non sono costose in termini di memoria o prestazioni ...

Ho scritto del codice per la paltform ARM7 integrata su IAR Workbench. Consiglio vivamente di fare affidamento su modelli per eseguire l'ottimizzazione in fase di compilazione e la previsione del percorso. Evita il casting dinamico come la peste. Usa i tratti / le politiche a tuo vantaggio, come prescritto nel libro di Andrei Alexandrescu, Design moderno in C ++ .

Lo so, può essere difficile da imparare, ma sono anche sicuro che il tuo prodotto trarrà vantaggio da questo approccio.

Un buon motivo e talvolta l'unico motivo è che non esiste ancora un compilatore C ++ per il sistema incorporato specifico. Questo è il caso ad esempio dei microcontrollori Microchip PIC . Sono molto facili da scrivere e hanno un compilatore C gratuito (in realtà, una leggera variante di C) ma non c'è nessun compilatore C ++ in vista.

Per un sistema limitato a 4K di ram, userei C, non C ++, solo per essere sicuro di vedere tutto quello che sta succedendo. Il fatto con C ++ è che è molto facile usare molte più risorse (sia CPU che memoria) di quanto sembri dare un'occhiata al codice. (Oh, creerò solo un altro BlerfObject per farlo ... whoops! Out of memory!)

Puoi farlo in C ++, come già accennato (no RTTI, no vtables, ecc, ecc.), ma passerai tutto il tempo assicurandoti che il tuo utilizzo del C ++ non ti allontani come faresti con il equivalente in C.

La mente umana affronta la complessità valutando il più possibile e quindi decidendo su cosa è importante concentrarsi, scartando o deprezzando il resto. Questa è l'intera base del marchio nel marketing, e in gran parte delle icone.

Per combattere questa tendenza, preferisco il C al C ++, perché ti costringe a pensare al tuo codice e al modo in cui interagisce con l'hardware in modo più ravvicinato - vicino inesorabilmente.

Per lunga esperienza, credo che C ti costringa a trovare soluzioni migliori ai problemi, in parte allontanandoti e non costringendoti a perdere un sacco di tempo soddisfacendo un vincolo che alcuni autori di compilatori pensavano fosse una buona idea, o capire cosa sta succedendo " sotto le copertine " ;.

In questo senso, linguaggi di basso livello come C ti fanno passare un sacco di tempo focalizzato sull'hardware e costruendo buoni pacchetti di struttura dati / algoritmo, mentre linguaggi di alto livello ti fanno passare un sacco di tempo a grattarti la testa chiedendoti cosa sta succedendo e perché non puoi fare qualcosa di perfettamente ragionevole nel tuo contesto e ambiente specifici. Battere il tuo compilatore in sottomissione (la tipizzazione forte è il peggior trasgressore) NON è un uso produttivo del tempo.

Probabilmente mi adatto bene allo stampo del programmatore - mi piace il controllo. A mio avviso, non è un difetto di personalità per un programmatore. Il controllo è ciò per cui siamo pagati. Più specificamente, controllo FLAWLESSLY. C ti dà molto più controllo di C ++.

Personalmente con 4kb di memoria direi che non otterrai molto più chilometraggio dal C ++, quindi scegli quello che sembra la migliore combinazione compilatore / runtime per il lavoro, dal momento che il linguaggio probabilmente non avrà molta importanza .

Nota che comunque non si tratta solo di linguaggio, dal momento che anche la biblioteca conta. Spesso le librerie C hanno una dimensione minima leggermente più piccola, ma potrei immaginare che una libreria C ++ destinata allo sviluppo integrato sia ridotta, quindi assicurati di testarla.

Alcuni affermano che i compilatori C possono generare codice molto più efficiente perché non devono supportare le funzionalità C ++ avanzate e possono quindi essere più aggressivi nelle loro ottimizzazioni.

Naturalmente, in questo caso potresti voler mettere alla prova i due compilatori specifici.

C vince sulla portabilità, perché è meno ambigua nelle specifiche del linguaggio; offrendo quindi una portabilità e una flessibilità molto migliori tra diversi compilatori ecc. (meno mal di testa).

Se non hai intenzione di sfruttare le funzionalità C ++ per soddisfare un'esigenza, vai con C.

  

Vedi qualche motivo per restare con C89 quando lo sviluppo è molto limitato   hardware (4kb di RAM)?

Personalmente, quando si tratta di applicazioni integrate (quando dico incorporato, non intendo dispositivi embedded con gonfiore WinCE, iPhone, ecc. oggi). Intendo dispositivi con risorse limitate. Preferisco il C, anche se ho lavorato un po 'anche con il C ++.

Ad esempio, il dispositivo di cui stai parlando ha 4kb di RAM, bene solo per quel motivo che non prenderei in considerazione C ++. Certo, potresti essere in grado di progettare qualcosa di piccolo usando C ++ e limitarne l'utilizzo nella tua applicazione come altri post hanno suggerito, ma C ++ "potrebbe " potenzialmente finirà per complicare / gonfiare la tua domanda sotto le coperte.

Hai intenzione di collegarti staticamente? Si consiglia di confrontare statica un'applicazione fittizia utilizzando c ++ vs c. Questo potrebbe portarti a considerare C invece. D'altra parte, se sei in grado di creare un'applicazione C ++ all'interno dei tuoi requisiti di memoria, provaci.

IMHO, In generale, nelle applicazioni integrate mi piace sapere tutto quello che sta succedendo. Chi sta usando le risorse di memoria / di sistema, quanto e perché? Quando li liberano?

Quando sviluppo per un target con X quantità di risorse, CPU, memoria, ecc. Cerco di rimanere sul lato inferiore dell'utilizzo di tali risorse perché non si sa mai quali requisiti futuri arriveranno, quindi aggiungendo più codice a il progetto che era "supposto" essere una semplice piccola applicazione ma alla fine diventa molto più grande.

La mia scelta è generalmente determinata dalla libreria C che decidiamo di utilizzare, che è selezionata in base a ciò che il dispositivo deve fare. Quindi, 9/10 volte ... finisce per essere uclibc o newlib e C. Il kernel che usiamo ha una grande influenza anche su questo, o se stiamo scrivendo il nostro kernel.

È anche una scelta di terreno comune. La maggior parte dei bravi programmatori C non ha problemi ad usare C ++ (anche se molti si lamentano per tutto il tempo che lo usano) .. ma non ho trovato il contrario vero (nella mia esperienza).

Su un progetto su cui stiamo lavorando (che coinvolge un kernel ground-up), la maggior parte delle cose viene eseguita in C, tuttavia un piccolo stack di rete è stato implementato in C ++, perché era solo più facile e meno problematico implementare la rete usando C ++ .

Il risultato finale è che il dispositivo funzionerà e supererà i test di accettazione oppure no. Se puoi implementare foo in xx stack e yy heap tramite il linguaggio z, provaci, usa tutto ciò che ti rende più produttivo.

La mia preferenza personale è C perché:

  • So cosa sta facendo ogni riga di codice (e costi)
  • Non conosco C ++ abbastanza bene da sapere cosa sta facendo (e costa) ogni riga di codice

Sì, mi sento a mio agio con il C ++, ma non lo so bene come lo so lo standard C.

Ora se puoi dire il contrario, beh, usa quello che sai :) Se funziona, supera i test, ecc. qual è il problema?

Quanta ROM / FLASH hai?

4kB di RAM possono ancora significare che ci sono centinaia di kilobyte di FLASH per memorizzare il codice effettivo e i dati statici. La RAM di queste dimensioni tende ad essere intesa solo per le variabili e se stai attento con quelle puoi adattare un programma abbastanza grande in termini di righe di codice in memoria.

Tuttavia, C ++ tende a rendere più difficile l'inserimento di codice e dati in FLASH, a causa delle regole di costruzione runtime per gli oggetti. In C, è possibile inserire facilmente una struttura costante nella memoria FLASH e accedervi come oggetto con costante hardware. In C ++, un oggetto costante richiederebbe al compilatore di valutare il costruttore in fase di compilazione, che penso sia ancora al di là di ciò che un compilatore C ++ può fare (teoricamente, potresti farlo, ma è molto molto difficile da fare in pratica) .

Quindi in una "piccola RAM", "grande FLASH" tipo di ambiente andrei con C ogni giorno. Si noti che una buona scelta intermedia i C99 che ha la maggior parte delle belle funzionalità C ++ per codice non di classe.

In generale no. Il C ++ è un super set di C. Questo sarebbe particolarmente vero per i nuovi progetti.

Sei sulla strada giusta per evitare costrutti in C ++ che possono essere costosi in termini di tempo della CPU e impronta di memoria.

Nota che alcune cose come il polimorfismo possono essere molto preziose: sono essenzialmente indicatori di funzione. Se trovi di averne bisogno, usali con saggezza.

Inoltre, una buona gestione delle eccezioni (ben progettata) può rendere l'app incorporata più affidabile di un'app che gestisce le cose con i codici di errore tradizionali.

L'unico motivo per preferire C IMHO sarebbe se il compilatore C ++ per la tua piattaforma non fosse in buone condizioni (buggy, scarsa ottimizzazione, ecc.)

Il libro C ++ per programmatori di giochi contiene informazioni relative alla dimensione del codice verrà aumentato in base alle funzionalità di C ++.

Hai inline in C99. Forse ti piacciono i dottori, ma la faccenda dei dottori giusti può essere disordinata. Se l'unico motivo rimanente per non usare C fosse lo spazio dei nomi, mi atterrerei davvero a C89. Questo perché potresti voler portarlo su una piattaforma integrata leggermente diversa. In seguito potresti iniziare a scrivere in C ++ sullo stesso codice. Ma attenzione quanto segue, in cui C ++ NON è un superset di C. So che hai detto di avere un compilatore C89, ma fa comunque questo confronto C ++ con C99, poiché il primo elemento, ad esempio, è vero per qualsiasi C poiché K & amp; R.

sizeof 'a' > 1 in C, non in C ++. In C hai array di lunghezza variabile VLA. Esempio: func (int i) {int a [i] . In C hai membri dell'array di variabili VAM. Esempio: struct {int b; int m [];} .

Voglio solo dire che non esiste un sistema con " ILLIMITATO " risorse. Tutto in questo mondo è limitato e OGNI applicazione dovrebbe considerare l'utilizzo delle risorse indipendentemente dal suo ASM, C, JAVA o JavaScript. I manichini che assegnano qualche Mbs "solo per essere sicuri" rende iPhone 7, Pixel e altri dispositivi estremamente flessibili. Non importa se hai 4kb o 40 Gb.

Ma da un'altra parte per contrastare lo spreco di risorse - è un tempo che ci vuole per risparmiare quelle risorse. Se ci vuole 1 settimana in più per scrivere una cosa semplice in C per salvare qualche segno di spunta e qualche byte invece di usare C ++ già implementato, testato e distribuito. Perché preoccuparsi? È come acquistare un hub USB. si puoi farcela da solo ma andrà meglio? più affidabile? più economico se conti il ??tuo tempo?

Solo un pensiero secondario: anche la potenza della tua presa non è illimitata. Prova a cercare da dove proviene e vedrai principalmente che sta bruciando qualcosa. La legge dell'energia e del materiale è ancora valida: nessun materiale o energia appare o scompare ma si trasforma.

Per problemi di allocazione della memoria, posso consigliare di utilizzare Quantum Platform e il suo approccio alla macchina a stati, poiché alloca tutto ciò di cui hai bisogno al momento dell'inizializzazione. Aiuta anche ad alleviare i problemi di contesa.

Questo prodotto funziona su C e C ++.

Dipende dal compilatore.

Non tutti i compilatori incorporati implementano tutto il C ++, e anche se lo fanno, potrebbero non essere bravi a evitare il gonfiore del codice (che è sempre un rischio con i template). Provalo con alcuni programmi più piccoli, vedi se riscontri problemi.

Ma dato un compilatore buono , no, non c'è motivo di non usare C ++.

Ho appena trovato un esempio su come utilizzare ISO C ++ per lo sviluppo incorporato, che potrebbe essere interessante per qualcuno che prende la decisione ogni volta che usa C ++ o C.

È stato fornito da Bjarne Stroustrup nella sua homepage :

Per uno sguardo a come ISO C ++ può essere usato per una seria programmazione di sistemi embedded, vedi standard di codifica C ++ per veicoli aerei JSF .

Post di risposta diversi a un aspetto diverso della domanda:

" malloc "

Alcune risposte precedenti ne parlano parecchio. Perché pensi che esista quella chiamata? Per una piattaforma veramente piccola, malloc tende a non essere disponibile, o decisamente opzionale. L'implementazione dell'allocazione dinamica della memoria tende ad essere significativa quando si ottiene un RTOS nella parte inferiore del sistema, ma fino ad allora è puramente pericoloso.

Puoi andare molto lontano senza di essa. Basti pensare a tutti i vecchi programmi FORTRAN che non avevano nemmeno uno stack adeguato per le variabili locali ...

Esistono diversi produttori di controller in tutto il mondo e quando dai un'occhiata ai loro progetti e ai set di istruzioni che devono essere utilizzati per la configurazione, potresti avere molti problemi. Il principale svantaggio del linguaggio assembly è che dipende dalla macchina / architettura. È davvero enorme chiedere a uno sviluppatore a memoria tutte le istruzioni esposte lì per realizzare la codifica per controller diversi. Questo è il motivo per cui C è diventato più popolare nello sviluppo embedded perché C è abbastanza alto da estrarre algoritmi e strutture dati da dettagli dipendenti dall'hardware, rendendo il codice sorgente portatile su un'ampia varietà di hardware di destinazione, linguaggio indipendente dall'architettura e molto facile da converti e gestisci il codice. Ma vediamo alcuni linguaggi di alto livello (orientati agli oggetti) come C, C ++, Python, Java ecc. Che si stanno evolvendo abbastanza da renderli sotto il radar dello sviluppo di sistemi embedded.

Su un sistema così limitato. Scegli l'assemblatore. Ti dà il controllo totale su ogni aspetto e non dà costi generali.

Probabilmente anche molto più veloce poiché molti compilatori incorporati non sono i migliori ottimizzatori (specialmente se lo si confronta con compilatori all'avanguardia come quelli che abbiamo per il desktop (Intel, Visual Studio, ecc.))

" yeah yeah ... ma c è riutilizzabile e ... " ;. Su un sistema così limitato, è probabile che non riutilizzerai gran parte di quel codice su un sistema diverso. Sullo stesso sistema, assemblatore è altrettanto riutilizzabile.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top