Warum programmiert ihr in C?
-
@volkart
Aber ich denke auch das überwiegend in C++ den schneller Code geschrieben wird!
Da bin ich mit dir völlig einig. Denn das gebastell unter C ist von manchen einfach eine Tragödie.
-
-lowbyte- schrieb:
@volkart
Aber ich denke auch das überwiegend in C++ den schneller Code geschrieben wird!
Da bin ich mit dir völlig einig. Denn das gebastell unter C ist von manchen einfach eine Tragödie.Das nennst Du "denken" ? Ich würde das ein Armutszeugnis nennen, geprägt von
intellektueller Schlichtheit ... Vielleicht nennst Du Dich auch noch "Programmierer",
ich hoffe nur, Deine Kenntnisse sind besser wie Dein Deutsch.
-
knivil schrieb:
Ich gehe ins Internet, warum muss ich den ganzen Kontent ignorieren, der mich nicht interessiert? Was ist denn das fuer eine bescheuerte Frage?
Ist nicht bescheuert. Die ewig gleichen, unfreundlichen, kaum konkret untermauerten C vs. C++-Flamewars sind hier schlicht offtopic. Es wäre mir sehr recht, wenn sie hier nicht mehr auftreten würden. Aber vielleicht liegt das an mir, und ich bin einfach nicht in der Lage, mit dem Geist der Zeit Schritt zu halten.
-
Wir hatten schon lange keinen so langen Thread C vs. C++. Fuer gewoehnlich sind sie im C++ Bereich zu finden. Und nicht nur das, allein die Qualitaet der Beitraege sucht seines Gleichen.
-
Ich finde einfach mann sollte sich mehr Respekt entgegen bringen, vorallem wenn man keine richtigen Argumente zum mehr Thema hat !
Nö, dann sollte man den Mund halten.
knivil schrieb:
Wir hatten schon lange keinen so langen Thread C vs. C++. Fuer gewoehnlich sind sie im C++ Bereich zu finden. Und nicht nur das, allein die Qualitaet der Beitraege sucht seines Gleichen.
Warum immer C gegen C++? Weil beide ein C im Namen haben? C ist ein sehr einfaches Werkzeug, das nur die allernötigsten Mittel anbietet um halbwegs strukturierte Programme zu schreiben. C++ ist eine umfangreiche Hochsprache, und tritt deshalb viel eher mit Java & Co in Konkurenz. Die Fälle, in denen sich ein verständiger Mensch ernsthaft zwischen C und C++ entscheiden muss, sind wohl sehr selten.
-
__-- schrieb:
volkard schrieb:
Eigentlich hatte ich eine Widerlegung meiner Aussage auf Seite 24 erwarte, wo ich schrieb, warum sowohl Anfänger- als auch Profi-Code in C++ die Tendenz hat, schneller als gleichwertiger Code in C zu sein.
also ich denke wir können uns darauf einigen, dass man in c mehr aufwand betreiben muß um auf die gleiche performance zu kommen.
Nein.
Ich meine da eine relativ neue Entwicklung, nämlich "zero cost" exception handling.
http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gnat_ugn_unw/Exception-Handling-Control.htmlthere is no overhead for exception handlers if no exception is raised
Recht neue Technik das, daher noch nicht in die C-Gemeinde allgemein durchgedrungen, fürchte ich.
In beiden Sprachen muß man die Rückgabe von malloc, fopen und so immer mit if noch überprüfen. In C++ wirft man eine Exception, in C returnt man.
Aber in C müssen alle Funktionen auf allen Ebenen mit if ihre Kinder überprüfen. Das muß man in C++ nicht, an passender Stelle steht beliebig viele Ebenen häher ein passendes catch. Effekt: viele ifs gespart und ersetzt durch gar nichts.
Also wird C++-Code von einem Programmierer, der auch in C zuhause ist, und nicht auf std::string und cout angewiesen ist, vermutlich schneller werden als gleichwertiger C-Code.
-
Natürlich ist C++ langsamer und Aufwendiger als C.
C:
#include <stdio.h> int main(int argc, char *argv[]) { printf("C rulez!!!!!!!"); return 0; }
C++:
#include <iostream>
#include <string>
#include <ctime>class Hello
{
public:
Hello(const std::string&);
void print();private:
std::string str;
void doSomethingUseless();
};Hello::Hello(const std::string &str) : str(str)
{
}void Hello::print()
{
int i;
for(i = 0; i < str.length(); i++)
{
doSomethingUseless();
std::cout << str[i];
}
}void Hello::doSomethingUseless()
{
time_t now;
time(&now);while( time(NULL) <= (now + 10));
}
int main(int argc, char *argv[])
{
Hello *h;
h = new Hello("C++ sucks\nEcht lahm das ganze");
h->print();
delete h;
return 0;
}
-
knivil schrieb:
Wir hatten schon lange keinen so langen Thread C vs. C++. Fuer gewoehnlich sind sie im C++ Bereich zu finden. Und nicht nur das, allein die Qualitaet der Beitraege sucht seines Gleichen.
Sind die Mods alle im Urlaub? Oder stehen die einfach auf Threads mit einer Trolldichte jenseits von Gut und Böse?
Scheppertreiber schrieb:
ich hoffe nur, Deine Kenntnisse sind besser wie Dein Deutsch.
Welch Ironie.
-
this->that schrieb:
knivil schrieb:
Wir hatten schon lange keinen so langen Thread C vs. C++. Fuer gewoehnlich sind sie im C++ Bereich zu finden. Und nicht nur das, allein die Qualitaet der Beitraege sucht seines Gleichen.
Sind die Mods alle im Urlaub? Oder stehen die einfach auf Threads mit einer Trolldichte jenseits von Gut und Böse?
Scheppertreiber schrieb:
ich hoffe nur, Deine Kenntnisse sind besser wie Dein Deutsch.
Welch Ironie.
Der Gameboy wieder ...
-
Möchtest du nicht noch dein Password preisgeben?
-
[quote="volkard]
Aber in C müssen alle Funktionen auf allen Ebenen mit if ihre Kinder überprüfen.[/quote]
Und genau das ist der grundlegende Irrtum. Muss man nämlich nicht. Und das hat auch nichts mit unsauberem Programmierstil zu tun. Wenn z.B. Josef so eine geniale Funktion erfindet, wie diese hier:void TranslateMessage(char** Buffer){ /* ... */
und dabei Hans die (mündliche) Zusage gibt, dass TranslateMessage garantiert funktioniert, wenn Buffer nicht NULL und mindestens BUFSIZE groß ist, dann braucht die Funktion von Josef nicht noch extra
if(Buffer) /* ... */
abfragen, wenn ihm Hans garantiert, niemals NULL reinzustecken.
Ein uneingeweihter Dritter (DAU) kann dann zwar immer noch NULL reinstecken.
Aber was, wenn gar nicht vorgesehen ist, dass je jemand anderer als der zuverlässige Hans die Funktion benutzen wird? -> Ergo: Überflüssige Doppelt- und Dreifachprüfung eingespart Kein Compiler der Welt könnte eine derartig überflüssige Doppele Überprüfung wegoptimieren, weil er von Josef's und Hans mündlicher Vereinbarung nichts weiß.
Aber was meinst Du, müsste wohl eine (hypothetische) DAU-sichere std::string::TranslateMessage(char** Buffer) Funktion tun?
Es bliebe ihr nicht erspart, dem ahnungslosen Aufrufer zuzutrauen, dass er eine NULL reinsteckt, und müsste dementsprechend die if() Abfrage, auf die das C-Team Josef + Hans verzichten konnte, implementieren. Oder man musste einen Exception-Handler für diesen Fall installieren (==Parallel-Thread) mit gigantischem Kontext-Wechsel Overhead (der momentane Zustand der Register muss zwischengespeichert werden, der Exception-Handler wird in die CPU geladen, nach Beendigung seiner Arbeit kann man nur noch abort() oder exit() aufrufen, da zu dem Zeitpunkt, als die Exception auftrat, der Stack in einem gänzlich zufälligen Zustand war, und es wird wohl auch die Freigabe von System-Handles oft genug zum Problem. Man kann gar nicht mehr genau eingrenzen, woher der Fehler überhaupt kam, und ein Ent-Buggen der Anwendung wird dementsprechend erschwert (idR unmöglich). Ganz zu schweigen von garantierten Deadlocks in Multi-Thread Anwendungen, die man sich mit Exceptions einbrockt.
Also, derartige (mündliche) Optimierungsmöglichkeiten wie in C hat man mit C++ gar nicht. Dort werden einem Exceptions & Co. jedenfalls von der Runtime aufgezwungen, ob man will oder nicht.
mfg
-
C++ ist eine übermüllte scheisse ... bei dem man mehr Abstraktion und Sicherheit gewinnen wollte und doch nichts erreichte hat, was der C Programmierer schon gar nicht braucht! Ihr C++' er kommt immer mit Argumenten die einfach nicht überzeugen!
Und das letzte Argument von Volkard ist gar nicht nennenswert.
-
Ausnahmekoenner schrieb:
... Aber was meinst Du, müsste wohl eine (hypothetische) DAU-sichere std::string::TranslateMessage(char** Buffer) Funktion tun? ..
Meinst du das ernst?
Du vergleichst also die sichere C++ Variante mit der unsicheren C Variante?
Oder gehst du davon aus, dass C++'ler so degeneriert sind, dass sie nicht miteinander kommunizieren können und deshalb die erste Variante nicht in Frage kommt?
-
Sie ist nur so unsicher wie der Programmierer der schreibt!
-
knivil schrieb:
Wir hatten schon lange keinen so langen Thread C vs. C++. Fuer gewoehnlich sind sie im C++ Bereich zu finden. Und nicht nur das, allein die Qualitaet der Beitraege sucht seines Gleichen.
siehste, hat c mehr Kante als c++ bzw. c--
-
Ausnahmekoenner schrieb:
volkard schrieb:
Aber in C müssen alle Funktionen auf allen Ebenen mit if ihre Kinder überprüfen.
Und genau das ist der grundlegende Irrtum. Muss man nämlich nicht. Und das hat auch nichts mit unsauberem Programmierstil zu tun. Wenn z.B. Josef so eine geniale Funktion erfindet, wie diese hier:
void TranslateMessage(char** Buffer){ /* ... */
und dabei Hans die (mündliche) Zusage gibt, dass TranslateMessage garantiert funktioniert, wenn Buffer nicht NULL und mindestens BUFSIZE groß ist
Das ist klar.
Aber sauviele Funktionen werden am Ende abgefragt werden müssen, weil innendrin oder in deren Kinder doch irgendwo syscalls lauern. Hast Du schonmal versucht, die *notwenignen* ifs alle einzubauen, statt sie wie üblich schlicht zu ignorieren?Ich rede nicht von unsinnigen Tests. Die sinnigen Tests. Die Notwendigen. Die, die schiefgehen können, weil eine Datei verschwunden ist, ein Puffer nicht allokiert werden konnte, ein Thread nicht erstellt werden konnte, eine Schriftart nicht geladen werden konnte und so weiter...
Und von den sinnigen Tests gibt es noch ausreichend viele. Und die haben wir in C++ zu Nullkosten, aber in C muß man dafür zahlen. Also kann man in C++ schnelleren Code bauen als in C.
-
Das mit den zero-cost-exceptions geht in C auch:
#define QUOTEME_(x) #x #define QUOTEME(x) QUOTEME_(x) #define THROW(msg) { fprintf(stderr, "%s in " __FILE__ ": " QUOTEME(__LINE__) "\ \n",(msg));exit(255);}
Wenn ein Fehler auftritt muss das Programm sowieso beendet werden.
Du wirst wahrscheinlich argumentieren, der Rückgabewert muss zuerst erst mit einem if der abgefragt werden und erst dann kann die Ausnahme geworfen (bzw. das Programm beenden) werden => zusätzliche Kosten.
Aber ich bin mir sicher, std::basic_fstream wurde irgendwie so geschrieben:
void // Rückgabewert auf seperater Zeile ist in C++ Pflicht basic_ifstream::init(__filebuf_type ft) { // Aufruf der C-Library des Systems um die Datei zu öffnen // Man beachte die schicke C++-Style-Kommentare // ... if (native_file_handle________ == 0) this->setstate(this_type________::failbit) // ruft eine komplexe Funktion auf, // die testet ob this->exceptions() auf // this_type________::failbit gesetzt ist und // wird dann eventuell eine exception werfen. }
Ich will gar nicht nachschauen, welche Member alles in std::fstream implementiert sind, wenn der insgesamt eine Grösste von
sizeof(std::fstream)=284
aufweist, wovon alleinstd::basic_streambuf<_CharT, _Traits>
folgende enthält:__c_lock _M_lock; __file_type _M_file; ios_base::openmode _M_mode; __state_type _M_state_beg; __state_type _M_state_cur; __state_type _M_state_last; char_type* _M_buf; size_t _M_buf_size; bool _M_buf_allocated; bool _M_reading; bool _M_writing; char_type _M_pback; char_type* _M_pback_cur_save; char_type* _M_pback_end_save; bool _M_pback_init; const __codecvt_type* _M_codecvt; char* _M_ext_buf; streamsize _M_ext_buf_size; const char* _M_ext_next; char* _M_ext_end;
Das alles für nll Funktionalität, versteht sich.
Folglich gilt für die files wie für die ausgabe wie für die strings wie für die gesamte Standardbibliothek folgendes: Sie ist zwar idiotensicher, aber inperformant. Lassen wir sie also für die weiteren Betrachtungen ausser acht.
Wie werden in C++ Threads implementiert? Man schreibt Wrapper um die Betriebssystemfunktionen in C.
Dann ist irgendwo ein C-Style Test
// initialisiere this->native_thread_ptr________ mit einem nativen Thread Pointer der offiziellen Funktion des Betriebssystemsif (this->native_thread_ptr________ == nullptr) // Jeder fähige C++-Programmierer hat irgendwo den templatigen nullptr-Trick liegen. { // neue Klammern gehören auf eine neue Zeile, alles andere ist Oracle Java-Style throw get_boost_from_this_boosty_library::i_can_t_create_the_thread_exception("Oh sorry, " "the Thread creation failed, so I have to throw the " "get_boost_from_this_boosty_library::i_can_t_create_the_thread_exception " "exception"); // hier liegt ein unhandlicher C-Style-String im Speicher, weil // C++-Style-Strings noch mehr Overhead verursachen }
Der Test ist in die Standard-Bibliothek ausgelagert, eine mündliche Abmachung zwischen dem Betriebssystementwickler und dem Ersteller der geschwindigkeitskritischen Anwendung ist verunmöglicht.
volkard schrieb:
Die, die schiefgehen können, weil eine Datei verschwunden ist, ein Puffer nicht allokiert werden konnte, ein Thread nicht erstellt werden konnte, eine Schriftart nicht geladen werden konnte und so weiter...
Datei habe ich oben gezeigt, den Thread auch und wenn eine Schriftart geladen wird gelten die vernichtenden Ausführungen immer noch.
DENN: Gtkmm, als einzige vernünftige C++ Komponentenbibliothek ist ein Wrapper von einer C-Library, Qt ist Performance-Bremse pur, wxWidgets kenne ich nicht (soll von Makros verseucht sein).
C wird verwendet um Bibliotheken zu schreiben, die von mehreren Sprachen benutzt werden können sollen, C++ bietet manchmal eine Wrapper dafür an.
Während du C folgendes schreibst, was zu deinem prophezeiten Overhead führt:
void foo(struct s *x) { // ... if (fail) { free(allocated_memory); return 1; return 0; } // Aufruf: if (foo(&x)) { /* do exception handling */ }
würdest du in in C++ das schreiben:
void foo(s& x) // keine klassen, unnötiger overhead { // ... if (fail) { // der Speicher wird vom Destruktor weggeräumt throw oops_i_fail_exception("..."); // <- hier steht eine ausführliche Problembeschreibung } // ein return brauchts nicht, weil wir ja keinen succeed-Wert mehr haben } Aufruf: foo(x)
Der fähige C-Programmierer übermittelt aber mündlich, was genau noch weggeräumt werden muss und dann sieht es so aus:
void foo(struct s *x) { // ... return fail; } // Aufruf: if (foo(&x)) { free(allocated_memory); /* do exception handling */ } // ich bin mir sicher, dass foo() jetzt _nicht_ fehlschlagen wird: foo(&x); // ich habe eine überflüssige if-Abfrage vermieden, die in C++ gemacht wurde
Wie genau hast du das mit den exceptions gemeint?
-
Wenn ein Fehler auftritt muss das Programm sowieso beendet werden.
Danach hab ich aufgehört zu lesen.
Wirklich unfassbar, wie wenig Ahnung die Cler von den C++ Konzepten haben.
-
Cönner schrieb:
Das mit den zero-cost-exceptions geht in C auch:
#define QUOTEME_(x) #x #define QUOTEME(x) QUOTEME_(x) #define THROW(msg) { fprintf(stderr, "%s in " __FILE__ ": " QUOTEME(__LINE__) "\ \n",(msg));exit(255);}
Wenn ein Fehler auftritt muss das Programm sowieso beendet werden.
Nicht unbedingt. Außerdem hast Du so keinerlei close oder flush oder gracefully disconnet oder sowas gemacht. Um das hinzukriegen, mußt Du doch die Kosten zahlen.
Können wir uns darauf einigen, daß man ein Programm sinnvollerweise in recht viele kleine Funktionen zerlegt? Du mußt das return 255 (nicht exit!) den ganzen Aufrufbaum entlang hochreichen bis zur main, um überall die offenen Sachen schließen zu können. Deswegen brauchst Du über den ganzen Aufrufbaum hinweg die bösen ifs (mal das free weggelassen, das geschieht in C++ ja auch).tuwas();//sicher fehlerfrei if(!(rc=subfunktion(...)) return rc;//hier kann was schiefgehen tuwas();//sicher fehlerfrei
In C++ reicht
tuwas();//sicher fehlerfrei subfunktion(...);//hier kann was schiefgehen tuwas();//sicher fehlerfrei
Das sind in C Mehrkosten, die Du nicht leugnen kannst.
OK, Du kannst sagen, daß Qt lahm wäre oder sowas. Aber der Hauptsatz der C++-Hasser, daß C++ vom Sprachdesign her prinzipiell langsamer wäre, ist hinfällig. Das Gegenteil ist sogar der Fall. C ist prinzipiell langsamer.
-
Cönner schrieb:
Aber ich bin mir sicher, std::basic_fstream wurde irgendwie so geschrieben:
...
Folglich gilt für die files wie für die ausgabe wie für die strings wie für die gesamte Standardbibliothek folgendes: Sie ist zwar idiotensicher, aber inperformant. Lassen wir sie also für die weiteren Betrachtungen ausser acht.Ich bin nicht glücklich mit der stream-Bibliothek. Deswegen verwende ich sie privat auch nicht. Versuch doch mal, std::sort zu schlagen. Dann weißt Du, daß da auch brutale Geschwindigkeit zu finden ist.
Cönner schrieb:
Wie werden in C++ Threads implementiert? Man schreibt Wrapper um die Betriebssystemfunktionen in C.
Dann ist irgendwo ein C-Style Test
// initialisiere this->native_thread_ptr________ mit einem nativen Thread Pointer der offiziellen Funktion des Betriebssystemsif (this->native_thread_ptr________ == nullptr) // Jeder fähige C++-Programmierer hat irgendwo den templatigen nullptr-Trick liegen. { // neue Klammern gehören auf eine neue Zeile, alles andere ist Oracle Java-Style throw get_boost_from_this_boosty_library::i_can_t_create_the_thread_exception("Oh sorry, " "the Thread creation failed, so I have to throw the " "get_boost_from_this_boosty_library::i_can_t_create_the_thread_exception " "exception"); // hier liegt ein unhandlicher C-Style-String im Speicher, weil // C++-Style-Strings noch mehr Overhead verursachen }
Der Test ist in die Standard-Bibliothek ausgelagert, eine mündliche Abmachung zwischen dem Betriebssystementwickler und dem Ersteller der geschwindigkeitskritischen Anwendung ist verunmöglicht.
Hä? Was soll das? Was wird da verunmöglicht? Den einen Test brauchen wir beide. Oder willst Du mündlich abmachen, daß es grundsätzlich möglich ist, einen neuen Thread anzulegen? In C++ ist es nur diese eine if. In C sind es alle ifs den Aufrufbaum hinauf bis zur main().
Cönner schrieb:
volkard schrieb:
Die, die schiefgehen können, weil eine Datei verschwunden ist, ein Puffer nicht allokiert werden konnte, ein Thread nicht erstellt werden konnte, eine Schriftart nicht geladen werden konnte und so weiter...
Datei habe ich oben gezeigt, den Thread auch und wenn eine Schriftart geladen wird gelten die vernichtenden Ausführungen immer noch.
Welche vernichtenden Ausführungen?
Cönner schrieb:
Während du C folgendes schreibst, was zu deinem prophezeiten Overhead führt:
void foo(struct s *x) { // ... if (fail) { free(allocated_memory); return 1; } return 0; } // Aufruf: if (foo(&x)) { /* do exception handling */ }
würdest du in in C++ das schreiben:
void foo(s& x) // keine klassen, unnötiger overhead { // ... if (fail) { // der Speicher wird vom Destruktor weggeräumt throw oops_i_fail_exception("..."); // <- hier steht eine ausführliche Problembeschreibung } // ein return brauchts nicht, weil wir ja keinen succeed-Wert mehr haben } Aufruf: foo(x)
Der fähige C-Programmierer übermittelt aber mündlich, was genau noch weggeräumt werden muss und dann sieht es so aus:
void foo(struct s *x) { // ... return fail; } // Aufruf: if (foo(&x)) { free(allocated_memory); /* do exception handling */ } // ich bin mir sicher, dass foo() jetzt _nicht_ fehlschlagen wird: foo(&x); // ich habe eine überflüssige if-Abfrage vermieden, die in C++ gemacht wurde
Wie genau hast du das mit den exceptions gemeint?
Verstehe ich nicht. Welches if(fail)? Dein C++-Code hat doch weder Hand noch Fuß. Klassen erzeugen außerdem keinen Overhead.