Wechsel von C ++ nach C.

83

Nach einigen Jahren Codierung in C ++ wurde mir kürzlich eine Jobcodierung in C im eingebetteten Bereich angeboten.

Abgesehen von der Frage, ob es richtig oder falsch ist, C ++ im eingebetteten Feld zu schließen, gibt es einige Funktionen / Redewendungen in C ++, die ich sehr vermissen würde. Nur um ein paar zu nennen:

  • Generische, typsichere Datenstrukturen (unter Verwendung von Vorlagen).
  • RAII. Insbesondere bei Funktionen mit mehreren Rückgabepunkten, z. B. wenn Sie nicht daran denken müssen, den Mutex an jedem Rückgabepunkt freizugeben.
  • Zerstörer im Allgemeinen. Wenn Sie also einmal einen d'tor für MyClass schreiben, muss MyOtherClass die MyClass-Instanz nicht explizit deinitialisieren, wenn eine MyClass-Instanz Mitglied von MyOtherClass ist - ihr d'tor wird automatisch aufgerufen.
  • Namespaces.

Welche Erfahrungen haben Sie mit dem Wechsel von C ++ zu C gemacht?
Welche C-Substitute haben Sie für Ihre bevorzugten C ++ - Funktionen / Redewendungen gefunden? Haben Sie C-Funktionen entdeckt, die C ++ gerne hätte?

George
quelle
12
Sollte wahrscheinlich ein Community-Wiki sein, wenn Sie nur nach Erfahrungen und nicht nach Rat fragen.
Peter Alexander
6
Sie könnten an Prog.SE interessiert sein .
11
@Peter: Fragen können vom OP nicht mehr CW gestellt werden, und es waren mehr Wiederholungen erforderlich als zu dem Zeitpunkt, als dies noch möglich war. Wenn Sie der Meinung sind, dass eine Frage aus einem anderen Grund zum Community-Wiki gemacht werden sollte, als um mehr Benutzern das Bearbeiten der "Community-eigenen" Beiträge zu ermöglichen, möchten Sie die Frage wirklich schließen.
4
Wäre diese Frage nicht besser für programmers.se geeignet? Da es definitiv eine "echte" Frage ist, sage ich, wir öffnen sie wieder und stimmen ab, um sie stattdessen zu verschieben. Und das ist nicht möglich. OK.
Lasse V. Karlsen
21
Der Umzug wird erst stattfinden, wenn die Prog SE aus der Beta ist, und auf jeden Fall denke ich, dass dieser Ansatz zur Qualitätssicherung einen verrückten Kopf hat. Es fragmentiert die Community, nervt die Benutzer, dupliziert die Fragen und Antworten. Es entsteht ein Chaos unorganisierter Informationen, die zuvor auf einer einzigen "Programmierer" -Seite zugänglich und navigierbar waren. Darüber hinaus sind es Fragen wie diese, die große Ansichten und unglaubliche Stimmen haben, die mich zwischen den 5 Schlagern und der Community als Ganzes verärgern.
Stefano Borini

Antworten:

68

Bei der Arbeit an einem eingebetteten Projekt habe ich einmal versucht, in allen C zu arbeiten, und konnte es einfach nicht aushalten. Es war so ausführlich, dass es schwierig war, etwas zu lesen. Außerdem gefielen mir die für eingebettete Container optimierten Container, die ich geschrieben hatte und die sich in weniger sichere und schwer zu reparierende #defineBlöcke verwandeln mussten .

Code, der in C ++ so aussah:

if(uart[0]->Send(pktQueue.Top(), sizeof(Packet)))
    pktQueue.Dequeue(1);

verwandelt sich in:

if(UART_uchar_SendBlock(uart[0], Queue_Packet_Top(pktQueue), sizeof(Packet)))
    Queue_Packet_Dequeue(pktQueue, 1);

Was viele Leute wahrscheinlich sagen werden, ist in Ordnung, wird aber lächerlich, wenn Sie mehr als ein paar "Methoden" -Aufrufe in einer Zeile ausführen müssen. Aus zwei Zeilen C ++ werden fünf Zeilen C (aufgrund von Zeilenlängenbeschränkungen von 80 Zeichen). Beide würden den gleichen Code generieren, es ist also nicht so, als würde sich der Zielprozessor darum kümmern!

Einmal (1995) habe ich versucht, viel C für ein Multiprozessor-Datenverarbeitungsprogramm zu schreiben. Die Art, bei der jeder Prozessor seinen eigenen Speicher und sein eigenes Programm hat. Der vom Hersteller bereitgestellte Compiler war ein C-Compiler (eine Art HighC-Derivat), seine Bibliotheken waren Closed Source, sodass ich GCC nicht zum Erstellen verwenden konnte, und ihre APIs wurden mit der Einstellung entworfen, dass Ihre Programme in erster Linie die Initialisierung / der Prozess sein würden Ich beende die Sorte, so dass die Kommunikation zwischen Prozessoren bestenfalls rudimentär war.

Ich kam ungefähr einen Monat, bevor ich aufgab, und fand eine Kopie von cfront fand und sie in die Makefiles hackte, damit ich C ++ verwenden konnte. Cfront unterstützte nicht einmal Vorlagen, aber der C ++ - Code war viel, viel klarer.

Generische, typsichere Datenstrukturen (unter Verwendung von Vorlagen).

Das, was C den Vorlagen am nächsten kommt, ist das Deklarieren einer Header-Datei mit viel Code, der wie folgt aussieht:

TYPE * Queue_##TYPE##_Top(Queue_##TYPE##* const this)
{ /* ... */ }

dann ziehen Sie es mit etwas wie:

#define TYPE Packet
#include "Queue.h"
#undef TYPE

Beachten Sie, dass dies für zusammengesetzte Typen (z. B. keine Warteschlangen von unsigned char) nur funktioniert, wenn Sie eine typedeferste erstellen .

Oh, und denken Sie daran, wenn dieser Code nirgendwo verwendet wird, wissen Sie nicht einmal, ob er syntaktisch korrekt ist.

BEARBEITEN: Noch etwas: Sie müssen die Instanziierung von Code manuell verwalten. Wenn Ihr "Vorlagen" -Code nicht alles ist Inline-Funktionen enthält, müssen Sie einige Steuerelemente festlegen, um sicherzustellen, dass die Dinge nur einmal instanziiert werden, damit Ihr Linker keinen Stapel "mehrerer Instanzen von Foo" -Fehlern ausspuckt .

Dazu müssen Sie das nicht inlinierte Material in einen Abschnitt "Implementierung" in Ihrer Header-Datei einfügen:

#ifdef implementation_##TYPE

/* Non-inlines, "static members", global definitions, etc. go here. */

#endif

Und dann müssen Sie an einer Stelle in Ihrem gesamten Code pro Vorlagenvariante :

#define TYPE Packet
#define implementation_Packet
#include "Queue.h"
#undef TYPE

Außerdem muss dieser Implementierungsabschnitt außerhalb der Standard #ifndef/ #define/ #endifLitanei liegen, da Sie die Vorlagen-Header-Datei möglicherweise in eine andere Header-Datei aufnehmen, diese jedoch anschließend in einer .cDatei instanziieren müssen .

Ja, es wird schnell hässlich. Deshalb versuchen es die meisten C-Programmierer nicht einmal.

RAII.

Insbesondere bei Funktionen mit mehreren Rückgabepunkten, z. B. wenn Sie nicht daran denken müssen, den Mutex an jedem Rückgabepunkt freizugeben.

Nun, vergessen Sie Ihre hübschen Code und erhalten auf alle Ihre Rückkehrpunkte (außer dem Ende der Funktion) verwendet wird gotos:

TYPE * Queue_##TYPE##_Top(Queue_##TYPE##* const this)
{
    TYPE * result;
    Mutex_Lock(this->lock);
    if(this->head == this->tail)
    {
        result = 0;
        goto Queue_##TYPE##_Top_exit:;
    }

    /* Figure out `result` for real, then fall through to... */

Queue_##TYPE##_Top_exit:
    Mutex_Lock(this->lock);
    return result;
}

Zerstörer im Allgemeinen.

Wenn Sie also einmal einen d'tor für MyClass schreiben, muss MyOtherClass die MyClass-Instanz nicht explizit deinitialisieren, wenn eine MyClass-Instanz Mitglied von MyOtherClass ist - ihr d'tor wird automatisch aufgerufen.

Die Objektkonstruktion muss explizit auf die gleiche Weise behandelt werden.

Namespaces.

Das ist eigentlich einfach zu beheben: Kleben Sie einfach ein Präfix auf jedes Symbol. Dies ist die Hauptursache für das Aufblähen der Quelle, über das ich zuvor gesprochen habe (da Klassen implizite Namespaces sind). Die C-Leute haben das schon immer gelebt und werden wahrscheinlich nicht sehen, was die große Sache ist.

YMMV

Mike DeSimone
quelle
59
Natürlich hasst du C, wenn du versuchst, es zu C ++ zu zwingen. Ich bezweifle, dass C ++ großartig aussehen würde, wenn Sie versuchen würden, Features aus $ more_expressive_language einzufügen. Keine Kritik an Ihrem Beitrag, nur eine Beobachtung :-)
In Bezug auf die Goto-statt-RAII-Technik: Ist es nicht ein Wartungs-Albtraum? Wenn Sie also einen Codepfad hinzufügen, der bereinigt werden muss, oder einfach nur die Reihenfolge der Dinge innerhalb der Funktion ändern, müssen Sie daran denken, am Ende zu den goto-Labels zu gehen und diese ebenfalls zu ändern. Ich würde gerne eine Technik sehen, die den Bereinigungscode irgendwie direkt neben dem registriert, was bereinigt werden muss.
george
2
@george: Ich hasse es, es zu sagen, aber der meiste eingebettete C-Code, den ich gesehen habe, ist für C-Standards ziemlich schlecht. Zum Beispiel arbeite ich gerade mit Atmels at91lib und es erfordert, dass Sie eine "board.h" -Datei schreiben, die der Großteil ihres Codes als Abhängigkeit abruft. (Für ihre Demo-Karte ist dieser Header 792 Zeilen lang.) Eine "LowLevelInit ()" - Funktion, die Sie für Ihre Karte anpassen müssen, besteht fast ausschließlich darin, Zugriffe zu registrieren, mit Zeilen wieAT91C_BASE_PMC->PMC_MOR = (0x37 << 16) | BOARD_OSCOUNT | AT91C_CKGR_MOSCRCEN | AT91C_CKGR_MOSCXTEN | AT91C_CKGR_MOSCSEL;
Mike DeSimone
1
Oh, und nichts dort sagt Ihnen, dass BOARD_OSCOUNT(was ist der Wert der Zeitüberschreitung für das Warten auf das Umschalten einer Uhr; klar, nicht wahr?) Tatsächlich ein #defineIn ist board.h. In derselben Funktion gibt es auch viel kopierten und eingefügten Spin-Loop-Code, der in einen zweizeiligen Code hätte umgewandelt werden sollen #define(und als ich genau das tat, wurden ein paar Bytes Code gespeichert und der Code erstellt Funktion besser lesbar, indem Registersätze und Spin-Loops deutlicher hervorgehoben werden). Einer der Hauptgründe für die Verwendung von C ist, dass Sie damit alles mikromanagen und optimieren können, aber der meiste Code, den ich gesehen habe, stört nicht.
Mike DeSimone
5
Stimmen Sie mit @Mads überein. Kein Grund, all das für Funktionen durchzugehen, die Sie nicht wirklich benötigen. Ich finde, ich mag einen ähnlichen Stil wie die GTK-Bibliothek. Definieren Sie Ihre "Klassen" als Strukturen und erstellen Sie dann konsistente Methoden wie my_class_new () und übergeben Sie diese an die "Methoden": my_class_do_this (my_class_instance)
Max
17

Ich bin aus einem anderen Grund (einer allergischen Reaktion;) von C ++ zu C gewechselt, und es gibt nur wenige Dinge, die ich vermisse und einige Dinge, die ich gewonnen habe. Wenn Sie sich an C99 halten, gibt es Konstrukte, mit denen Sie insbesondere sehr gut und sicher programmieren können

  • Bestimmte Initialisierer (eventuell kombiniert mit Makros) machen die Initialisierung einfacher Klassen so schmerzlos wie Konstruktoren
  • zusammengesetzte Literale für temporäre Variablen
  • forDie Variable -scope kann Ihnen dabei helfen, eine bereichsgebundene Ressourcenverwaltung durchzuführen , insbesondere um sicherzustellen, dass unlockMutexe oder freeArrays auch bei vorläufigen Funktionsrückgaben vorhanden sind
  • __VA_ARGS__ Makros können verwendet werden, um Standardargumente für Funktionen zu haben und um das Abrollen von Code durchzuführen
  • inline Funktionen und Makros, die sich gut kombinieren lassen, um überlastete Funktionen zu ersetzen
Jens Gustedt
quelle
2
@ Mike: Für welchen Teil im Besonderen? Wenn Sie dem Link folgen, den ich für die forBereiche angegeben habe, landen Sie auf P99, wo Sie sich auch nach Beispielen und Beschreibungen der anderen Teile umsehen können.
Jens Gustedt
1
@ Mike: Los geht's.
George
@george: Danke! @Jens: Beispiele der anderen vier. Ich bin auf meinem C zurückgefallen; Zuletzt hörte ich, dass sie automatisch zugewiesene Arrays (z. B. Stack-Arrays void DoSomething(unsigned char* buf, size_t bufSize) { unsigned char temp[bufSize]; ... }) zur Laufzeitgröße (z. B. Stack) und Strukturinitialisierung durch Feldnamen (z. B. ) hinzufügten. struct Foo bar = { .field1 = 5, .field2 = 10 };Letzteres würde ich gerne in C ++ sehen, insbesondere bei Nicht-POD-Objekten (z. B. UART uart[2] = { UART(0x378), UART(0x278) };). .
Mike DeSimone
@Mike: Ja, es gibt Arrays mit variabler Länge (VLA), deren Verwendung jedoch aufgrund eines möglichen Stapelüberlaufs möglicherweise etwas gefährlich ist. Die Sekunde, die Sie beschreiben, ist genau der "designierte Initialisierer", also gehen Sie mit Ihrem eigenen Beispiel ;-) Für die anderen finden Sie Informationen über den Link P99 oben, wenn Sie auf "verwandte Seiten" klicken.
Jens Gustedt
8

Für C
gibt es nichts Vergleichbares wie die STL. Es sind Bibliotheken verfügbar, die ähnliche Funktionen bieten, aber nicht mehr integriert sind.

Ich denke, das wäre eines meiner größten Probleme ... Zu wissen, mit welchem ​​Tool ich das Problem lösen könnte, aber nicht die Tools in der Sprache zur Verfügung zu haben, die ich verwenden muss.

MOnsDaR
quelle
Dies ist wahr. Kann jemand erläutern, welche Containerklassenbibliotheken für C verwendet werden sollen? Oder lautet die Antwort "Schreibe selbst eins"?
Sandeep
@Sandeep: Für den Anfang ist diese Antwort nur richtig, wenn Container nicht in der Standardbibliothek enthalten sind. Abgesehen davon, dass es kein STL-Äquivalent gibt (der beste Teil von C ++), ist die C-Standardbibliothek weit überlegen. POSIX enthält zusätzlich zu qsort in libc tsearch, lsearch, hsearch und bsearch. Glib ist der definitive "Boost" von C, werfen Sie einen Blick darauf, es ist voll mit Leckereien (Behälter enthalten). library.gnome.org/devel/glib/stable . Glib lässt sich auch in Gtk + integrieren, eine Kombination, die Boost und Qt übertrifft. Es gibt auch libapr, beliebt für xplatform-Inhalte wie Subversion und Apache.
Matt Joiner
Ich kann keine Bibliotheken von c finden, die mit der stl konkurrieren könnten, sie sind schwieriger zu verwenden, schwieriger zu warten, die Leistung ist nicht der Rivale von stl, wenn sie die c-Bibliotheken so allgemein wie stl halten wollen die Einschränkung von c und die Gründe, warum wir so etwas wie stl nicht in der c-Bibliothek haben können, weil c einfach nicht die Fähigkeit hat, so etwas wie stl zu entwickeln.
StereoMatching
8

Der Unterschied zwischen C und C ++ ist die Vorhersagbarkeit des Verhaltens des Codes.

Es ist einfacher, mit großer Genauigkeit vorherzusagen, was Ihr Code in C tun wird. In C ++ wird es möglicherweise etwas schwieriger, eine genaue Vorhersage zu erstellen.

Die Vorhersagbarkeit in C gibt Ihnen eine bessere Kontrolle darüber, was Ihr Code tut, aber das bedeutet auch, dass Sie mehr tun müssen.

In C ++ können Sie weniger Code schreiben, um das Gleiche zu erreichen, aber (zumindest für mich) ich habe gelegentlich Probleme zu wissen, wie der Objektcode im Speicher angeordnet ist und welches Verhalten erwartet wird.

ds
quelle
4
Immer wenn ich mir Gedanken darüber mache, was der Code wirklich tut, füge ich das -sFlag hinzu, gccum den Assembly-Dump abzurufen, nach der betreffenden Funktion zu suchen und mit dem Lesen zu beginnen. Es ist eine großartige Möglichkeit, die Macken einer kompilierten Sprache zu lernen.
Mike DeSimone
2
Es ist auch Zeitverschwendung, da eine von C ++ generierte Assembly dem Lesen von Perl gleicht. Bravo, weil er sowieso gesucht hat.
Matt Joiner
7

In meiner Arbeit - die übrigens eingebettet ist - wechsle ich ständig zwischen C und C ++ hin und her.

Wenn ich in C bin, vermisse ich von C ++:

  • Vorlagen (einschließlich, aber nicht beschränkt auf STL-Container). Ich verwende sie für spezielle Zähler, Pufferpools usw. (habe meine eigene Bibliothek mit Klassenvorlagen und Funktionsvorlagen aufgebaut, die ich in verschiedenen eingebetteten Projekten verwende).

  • sehr leistungsfähige Standardbibliothek

  • Destruktoren, die natürlich RAII ermöglichen (Mutexe, Interrupt-Deaktivierung, Tracing usw.)

  • Zugriffsspezifizierer, um besser durchzusetzen, wer was verwenden (nicht sehen) kann

Ich verwende die Vererbung für größere Projekte, und die integrierte Unterstützung von C ++ ist viel sauberer und schöner als der C-Hack, bei dem die Basisklasse als erstes Mitglied eingebettet wird (ganz zu schweigen vom automatischen Aufruf von Konstruktoren, Initialisierungslisten usw.). ) aber die oben aufgeführten Punkte sind die, die ich am meisten vermisse.

Außerdem verwendet wahrscheinlich nur etwa ein Drittel der eingebetteten C ++ - Projekte, an denen ich arbeite, Ausnahmen, sodass ich mich daran gewöhnt habe, ohne sie zu leben, damit ich sie nicht zu sehr vermisse, wenn ich zurück zu C gehe.

Auf der anderen Seite gibt es, wenn ich zu einem C-Projekt mit einer beträchtlichen Anzahl von Entwicklern zurückkehre, ganze Klassen von C ++ - Problemen, die ich gewohnt bin, Leuten zu erklären, die weggehen. Meistens Probleme aufgrund der Komplexität von C ++ und Leute, die glauben zu wissen, was los ist, aber sie sind wirklich am "C mit Klassen" Teil der C ++ - Konfidenzkurve .

Wenn ich die Wahl habe, würde ich es vorziehen, C ++ für ein Projekt zu verwenden, aber nur, wenn das Team ziemlich solide in der Sprache ist. Natürlich auch unter der Annahme, dass es sich nicht um ein 8K μC-Projekt handelt, bei dem ich sowieso effektiv "C" schreibe.

Dan
quelle
2
Diese "C ++ Confidence Curve" stört mich ein bisschen. Die Art und Weise, wie es geschrieben ist, und die Kommentare implizieren, dass C ++ hoffnungslos ist, eine verlorene Sache oder was auch immer. Vermisse ich etwas
Mike DeSimone
Tauchen Sie ein, wir sehen uns in ein paar Jahren. Die meisten guten Programmierer kommen mit einem sauren Geschmack auf die andere Seite.
Matt Joiner
3

Einige Beobachtungen

  • Wenn Sie nicht vorhaben, Ihren C ++ - Compiler zum Erstellen Ihres C zu verwenden (was möglich ist, wenn Sie sich an eine genau definierte Teilmenge von C ++ halten), werden Sie bald feststellen, dass Ihr Compiler in C einen Kompilierungsfehler in C ++ zulässt.
  • Keine kryptischen Vorlagenfehler mehr (yay!)
  • Keine (sprachunterstützte) objektorientierte Programmierung
hhafez
quelle
C unterstützt keine Vorlage bedeutet nicht, dass wir keine "generischen Paradigmen" benötigen. In C müssen Sie void * und ein Makro verwenden, um die Vorlage nachzuahmen, wenn Sie "generische Paradigmen" benötigen. Void * ist nicht typsicher, die Fehler des Makros auch ziemlich beschissen, nicht besser als Vorlage. Vorlage ist viel einfacher zu lesen und zu pflegen als Makro, plus Typ sicher.
StereoMatching
2

Ziemlich genau die gleichen Gründe, die ich für die Verwendung von C ++ oder einer Mischung aus C / C ++ anstelle von reinem C habe. Ich kann ohne Namespaces leben, aber ich benutze sie die ganze Zeit, wenn der Codestandard dies zulässt. Der Grund dafür ist, dass Sie in C ++ viel kompakteren Code schreiben können. Das ist sehr nützlich für mich, ich schreibe Server in C ++, die ab und zu zum Absturz neigen. An diesem Punkt hilft es sehr, wenn der Code, den Sie betrachten, kurz und beständig ist. Betrachten Sie beispielsweise den folgenden Code:

uint32_t 
ScoreList::FindHighScore(
  uint32_t p_PlayerId)
{
  MutexLock lock(m_Lock); 

  uint32_t highScore = 0; 
  for(int i = 0; i < m_Players.Size(); i++)
  {
    Player& player = m_Players[i]; 
    if(player.m_Score > highScore)
      highScore = player.m_Score; 
  }

  return highScore; 
}

In C sieht das so aus:

uint32_t 
ScoreList_getHighScore(
  ScoreList* p_ScoreList)
{
  uint32_t highScore = 0; 

  Mutex_Lock(p_ScoreList->m_Lock); 

  for(int i = 0; i < Array_GetSize(p_ScoreList->m_Players); i++)
  {
    Player* player = p_ScoreList->m_Players[i]; 
    if(player->m_Score > highScore)
      highScore = player->m_Score; 
  }

  Mutex_UnLock(p_ScoreList->m_Lock);

  return highScore; 
}

Keine Welt voller Unterschiede. Noch eine Codezeile, aber das summiert sich. Normalerweise versuchen Sie Ihr Bestes, um es sauber und schlank zu halten, aber manchmal müssen Sie etwas Komplexeres tun. Und in solchen Situationen schätzen Sie Ihre Zeilenanzahl. Eine weitere Zeile ist eine weitere Sache, die Sie sich ansehen müssen, wenn Sie herausfinden möchten, warum Ihr Broadcast-Netzwerk plötzlich keine Nachrichten mehr übermittelt.

Wie auch immer, ich finde, dass C ++ es mir ermöglicht, komplexere Dinge auf sichere Weise zu erledigen.

Antiheld
quelle
In C können Sie dies nicht "für (int i = 0") tun.
Victor
6
Victor es ist jedoch gültig c99 (oder kompilieren c mit einem c ++ - Compiler für ein Tippproblem).
Roman A. Taycher
Ich kann der Sicherheit nicht vertrauen. Ihr Mutex hat also einen Gültigkeitsbereich. Jetzt wissen Sie nicht, warum es freigeschaltet wird, wenn eine Ausnahme "durchwandert". Sie wissen nicht einmal, wann es freigeschaltet wird. Jeder Teil Ihres Codes könnte entscheiden, ob er genug hat und wirft. Diese zusätzlichen impliziten "Sicherheitsvorkehrungen" können Fehler maskieren.
Matt Joiner
Matt, wir wissen, warum es entsperrt wurde. Im Normalfall, wenn das Programm das Ende des Bereichs erreicht, wird der Mutex entsperrt, wir müssen ihn nicht mit handgemachten Codes entsperren, es ist ein Alptraum für die Wartung Wenn eine Ausnahme auftritt, wird der Mutex entsperrt, und wir können die Ausnahme abfangen und die Fehlermeldung daraus lesen. Die Fehlermeldung ist gut genug oder nicht. Dies hängt davon ab, wie Sie mit der Ausnahme spielen.
StereoMatching
0

Ich denke, das Hauptproblem, warum es schwieriger ist, C ++ in einer eingebetteten Umgebung zu akzeptieren, ist der Mangel an Ingenieuren, die verstehen, wie man C ++ richtig verwendet.

Ja, die gleiche Argumentation kann auch auf C angewendet werden, aber zum Glück gibt es in C nicht so viele Fallstricke, die sich in den Fuß schießen können. In C ++ hingegen müssen Sie wissen, wann Sie bestimmte Funktionen in C ++ nicht verwenden sollen.

Alles in allem mag ich c ++. Ich verwende das auf der Ebene der O / S-Dienste, des Treibers, des Verwaltungscodes usw. Aber wenn Ihr Team nicht genug Erfahrung damit hat, wird es eine schwierige Herausforderung.

Ich hatte Erfahrung mit beiden. Als der Rest des Teams nicht dazu bereit war, war es eine totale Katastrophe. Auf der anderen Seite war es eine gute Erfahrung.

KOkon
quelle
0

Ja! Ich habe beide Sprachen erlebt und fand, dass C ++ eine freundlichere Sprache ist. Es erleichtert mit mehr Funktionen. Es ist besser zu sagen, dass C ++ eine Obermenge der C-Sprache ist, da es zusätzliche Funktionen wie Polymorphismus, Interitanz, Überladung von Operatoren und Funktionen sowie benutzerdefinierte Datentypen bietet, die in C nicht wirklich unterstützt werden. Die tausend Codezeilen werden auf wenige Zeilen reduziert Die Hilfe der objektorientierten Programmierung ist der Hauptgrund für den Wechsel von C nach C ++.

kaynat liaqat
quelle
C ++ ist wirklich keine Obermenge von C; Es ist sehr einfach, C-Code zu schreiben, der auf einem C ++ - Compiler nicht kompiliert werden kann. Andererseits war (ist?) Objective-C eine strikte Obermenge von C.
ex nihilo
@exnihilo Die Konventionsobermenge hier besteht darin, zu definieren, dass C ++ mehr Funktionen bietet. Es verbessert auch die Syntax und Semantik und verringert die Fehlerwahrscheinlichkeit. Es gibt Code, der nicht in C ++ kompiliert wurde, aber in C kann, wie const int a; Dies führt in C ++ zu einem Fehler, da zum Zeitpunkt der Deklaration eine Konstante initialisiert werden muss, während in C das Konzept kompiliert wird. Superset ist also keine feste Regel wie in der Mathematik (A⊂B), sondern eine Annäherung, dass C ++ zusätzliche Funktionen wie das objektorientierte Konzept bietet.
Kaynat Liaqat