'bla' is promoted to 'bla' when passed throug '...' - va_arg Probleme
-
Oder vermeide variable Argumentlisten gänzlich. Aufgrund mangelnder Typsicherheit und Inkompatibilität zu Klassentypen passen diese nicht wirklich zu C++ und sind sehr fehleranfällig.
Eine gute Alternative ist die Übergabe eines Containers, oder je nachdem auch die Überladung von Operatoren.
-
Bashar schrieb:
Genau das heißt es. Ist aber kein Problem, dann hol halt ein int raus und caste es dann nach char. Genau das umgekehrte passiert ja beim Aufruf deiner Funktion, chars werden nach int 'promoted'.
Aber wenn ich ein int hole (4 Byte) und dann nach char caste, dann sind da drei byte zu viel vom Stackframe gelesen, die dann ev. zu einem anderen Parameter gehören, oder?
Nexus schrieb:
Oder vermeide variable Argumentlisten gänzlich. Aufgrund mangelnder Typsicherheit und Inkompatibilität zu Klassentypen passen diese nicht wirklich zu C++ und sind sehr fehleranfällig.
Eine gute Alternative ist die Übergabe eines Containers, oder je nachdem auch die Überladung von Operatoren.
Da hast du natürlich vollkommen recht, aber ich brauche für die Funktion eine einfache, schnelle Lösung, da sie nur temporär ist. Da eine Klasse zu erstellen und Operatoren zu überladen ist mir für diesen Zweck zu viel arbeit.
-
blitzmaster schrieb:
Da hast du natürlich vollkommen recht, aber ich brauche für die Funktion eine einfache, schnelle Lösung, da sie nur temporär ist. Da eine Klasse zu erstellen und Operatoren zu überladen ist mir für diesen Zweck zu viel arbeit.
Okay, wenn das nur vorübergehend ist oder du genau weisst, was du tust. Falls es doch etwas Ernsthafteres werden sollte, würde ich mir das nochmals stark überlegen, zumal auch die Wartbarkeit betroffen sein kann. Beim Debuggen solltest du diesen Code einfach als erstes in Betracht ziehen.

Ist deine Funktion sowas ähnliches wie
printf(), wo du Formatflags übergibst? Falls ja, wäre dir eine typsichere Methode analog zu den C++-Streams nicht lieber? Sodass du schreiben könntest:DebugPrint << "Ein Fehler in Zeile " << 252 << " mit dem Zeichen " << 'o';
-
blitzmaster schrieb:
Bashar schrieb:
Genau das heißt es. Ist aber kein Problem, dann hol halt ein int raus und caste es dann nach char. Genau das umgekehrte passiert ja beim Aufruf deiner Funktion, chars werden nach int 'promoted'.
Aber wenn ich ein int hole (4 Byte) und dann nach char caste, dann sind da drei byte zu viel vom Stackframe gelesen, die dann ev. zu einem anderen Parameter gehören, oder?
Nein, du hast den zweiten Satz ignoriert
Der char wird beim Aufruf promoted, d.h. als int übergeben, und damit passt es wieder zusammen.
-
blitzmaster schrieb:
Da hast du natürlich vollkommen recht, aber ich brauche für die Funktion eine einfache, schnelle Lösung, da sie nur temporär ist. Da eine Klasse zu erstellen und Operatoren zu überladen ist mir für diesen Zweck zu viel arbeit.
Dann lass die vorübergehende Lösung weg und nimm dir gleich die Zeit, die endgültige Lösung einzubauen. Besser als Zeit zu verplempern indem du eine provisorische Lösung einbaust, deren Umsetzung du erst hier erfragen musst, die zudem fehleranfällig ist und dich deshalb unabsehbar viel Zeit für die Fehlersuche kosten wird.
-
Nexus schrieb:
Ist deine Funktion sowas ähnliches wie
printf(), wo du Formatflags übergibst? Falls ja, wäre dir eine typsichere Methode analog zu den C++-Streams nicht lieber? Sodass du schreiben könntest:DebugPrint << "Ein Fehler in Zeile " << 252 << " mit dem Zeichen " << 'o';Das stimmt, aber da muss ich doch die << operatoren überladen, oder? Und da kenn ich mich noch weniger aus... also^^
pumuckl schrieb:
blitzmaster schrieb:
Da hast du natürlich vollkommen recht, aber ich brauche für die Funktion eine einfache, schnelle Lösung, da sie nur temporär ist. Da eine Klasse zu erstellen und Operatoren zu überladen ist mir für diesen Zweck zu viel arbeit.
Dann lass die vorübergehende Lösung weg und nimm dir gleich die Zeit, die endgültige Lösung einzubauen. Besser als Zeit zu verplempern indem du eine provisorische Lösung einbaust, deren Umsetzung du erst hier erfragen musst, die zudem fehleranfällig ist und dich deshalb unabsehbar viel Zeit für die Fehlersuche kosten wird.
Da aber die finale Lösung garkeine DEBUG meldungen enthalten wird, reicht das mal aus^^
-
void DebugMessage(const char* pcFormat, ... ) { char szText[256]; char curtime[256]; char msg[256]; SYSTEMTIME Systime; va_list ArgList; memset( szText, 0, sizeof( szText )); memset( &Systime, 0, sizeof( SYSTEMTIME )); GetLocalTime( &Systime ); _snprintf(curtime, sizeof( szText ) - 1, "%02d:%02d:%02d\0", Systime.wHour, Systime.wMinute, Systime.wSecond); va_start( ArgList, pcFormat ); vsnprintf_s( &szText[ strlen( szText ) ], sizeof( szText ) - strlen( szText ), sizeof( szText ) - strlen( szText ) - 1, pcFormat, ArgList ); va_end(ArgList); _snprintf(msg, 255, "[%s] %s\n", curtime, szText); std::cout << szText << "\n"; }
-
@______@ schrieb:
...*würg*
Warum deklarierst Du alle Variablen zuerst?
Was ist SYSTEMTIME?
Was ist dieses _snprintf? Warum verwendest Du reservierte Bezeichner?
Warum speicherst Du das Ergebnis von strlen nicht zwischen?
Warum fragst Du überhaupt einen String, den Du gerade auf 0 gesetzt hast, wie lang er ist?
Warum setzt Du die Puffer nicht gleich bei der Initialisierung auf 0?
Warum überhaupt drei Puffer?
Warum verwendest Du keine strings
Warum können Deine Zeilen nur 256 Zeichen lang sein?Fragen über Fragen...
-
LordJaxom schrieb:
@______@ schrieb:
...*würg*
Warum deklarierst Du alle Variablen zuerst?
Was ist SYSTEMTIME?
Was ist dieses _snprintf? Warum verwendest Du reservierte Bezeichner?
Warum speicherst Du das Ergebnis von strlen nicht zwischen?
Warum fragst Du überhaupt einen String, den Du gerade auf 0 gesetzt hast, wie lang er ist?
Warum setzt Du die Puffer nicht gleich bei der Initialisierung auf 0?
Warum überhaupt drei Puffer?
Warum verwendest Du keine strings
Warum können Deine Zeilen nur 256 Zeichen lang sein?Fragen über Fragen...
1. ) Nennt man wahrscheinlich persönlichen Stil.
2. ) WinAPI.
3. ) http://msdn.microsoft.com/de-de/library/2ts7cx93(VS.80).aspx
4. ) Versteh nicht was du meinst.
5. ) Mach ich nicht.
6. ) Weil ich [..] = {0}; hässlich finde.
7. ) Weil ich 3 brauchte.
8. ) Wieso sollte ich? Wenn ich mit WinAPI arbeite, benutze ich keine.
9. ) Weil meine Nachrichten nicht länger als 256 seien können.
-
@______@ schrieb:
1. ) Nennt man wahrscheinlich persönlichen Stil.
Oder veralteten schlecht wartbaren C-Stil
4. ) Versteh nicht was du meinst.
Er meint dass du zweimal hintereinander stlen aufrufst - du könntest das auf einen Aufruf reduzieren wenn du das Ergebnis zwischenspeicherst.
5. ) Mach ich nicht.
Doch. Du machst ein memset auf 0 und fragst danach strlen ab - strlen liefert die Zahl der Zeichen bis zur ersten 0.
8. ) Wieso sollte ich? Wenn ich mit WinAPI arbeite, benutze ich keine.
Ist kein Argument. Warum du solltest: Typsicherheit, Lesbarkeit des Codes, Schutz gegen Overflows, keine unnötigen Längenbeschränkungen. WinAPI ist kein Argument um C-Stil zu programmieren wo man C++ verwenden könnte.
Alles in allem ist das was du uns da vorgelegt hast ein einziger Klumpen schlecht lesbarer (und daher schlecht wartbarer) C-Code, in den sich aus Versehen eine Zeile C++ I/O verirrt hat.
-
blitzmaster schrieb:
Das stimmt, aber da muss ich doch die << operatoren überladen, oder? Und da kenn ich mich noch weniger aus... also^^
Du kannst natürlich auch die bestehenden Streams nehmen. Wohin willst du schreiben? Auf die Konsole? In Dateien? Sonst wo hin? Du kannst die Standardausgaben auch umleiten.
-
Ich hätte wohl erwähnen sollen dass es sich hier um eine Funktion in meinem eigenen OS also in meinem Kernel handelt, den ich zur Zeit in C++ neu schreibe.
Deshalb muss ich wohl den << operator für meine Video - Klasse überladen.
Aber jetzt die Frage: was nimmt der für nen Typ? Der sinn von dem ist ja, dass ich alles da hinschreiben kann, oder? Ich nehme an, das ist ein binärer operator.
Was hat er für eine Rückgabe?
-
blitzmaster schrieb:
Ich hätte wohl erwähnen sollen dass es sich hier um eine Funktion in meinem eigenen OS also in meinem Kernel handelt, den ich zur Zeit in C++ neu schreibe.
Deshalb muss ich wohl den << operator für meine Video - Klasse überladen.
Aber jetzt die Frage: was nimmt der für nen Typ? Der sinn von dem ist ja, dass ich alles da hinschreiben kann, oder? Ich nehme an, das ist ein binärer operator.
Was hat er für eine Rückgabe?Wenn DebugPrint ein einfacher std::ostream (oder davon abgeleitet) ist, brauchst du garnichts zu überladen, solange du keine selbstdefinierten Objekte ausgeben willst.
Mal ganz ehrlich: du schreibst einen eigenen Kernel in einer Sprache, die du noch nicht beherrscht? Halte ich für keine gute Idee. Und bevor du widersprichst: Streams und Streamoperatoren sind Grundlagen von C++. Dass du die nicht kennst bzw. nichtmal annähernd zu wissen scheinst wie das Überladen dort funktioniert, heißt, dass du es nicht beherrscht. Nach dem was du bisher preisgegeben hast mutmaße ich mal, dass dein Kernel bisher in C geschrieben ist. Wenn du ihn in C++ umschreiben willst, solltest du C++ kennen und verstehen und vor allem von C wegkommen, also umdenken, damit du nicht in das Anfang der 90er von einigen so gerne praktizierte "C mit ein paar Klassen" verfällst. Das ist nämlich nichts halbes und nichts ganzes und einfach nur schrecklich.
-
Da das ganze ein Kernel ist, muss ich auf die std verzichten, bis ich mir selbst eine geschrieben habe. Das Verzichten bezieht sich zwar nur auf die RTI, Ecpetions, new/delete, Exceptions und ein paar andere Sache; aber es ist mir zuviel Arbeit (bzw. habe ich mich auch noch nicht damit beschäftigt) mir da sozusagen die Rosinen herauszupicken.
Und mein Kernel war vorher nicht in C geschrieben, sondern in Assembler. Ich habe auch lange überlegt das ganze in C zu schreiben. Aber gerade die Vorteile der OOP haben mich überzeugt ihn in C++ zu schreiben. Ich muss aber auch sagen, dass nicht nicht unbediengt tollen und schön anzusehenden C++ Code schreiben möchte, sondern etwas, womit ich erreichen kann was ich will und vor allem auch wie ich es will. Um erhlich zu sein läuft das schon auf ein "C mit ein paar Klassen" (vl. ein bisschen mehr) hinaus.
-
blitzmaster schrieb:
Das Verzichten bezieht sich zwar nur auf die RTI, Ecpetions, new/delete, Exceptions und ein paar andere Sache;
Ach so, wenns sonst nichts ist... Dann wirds wirklich nur ein C mit Klassen. Und cout kannst dann auch gleich knicken, da die std::ostreams auch irgendwo auf RTTI setzen (virtuelle Funktionen gehören dazu). Allerdings ist Polymorphie mitsamt virtuellen Funktionen eine der Hauptstärken von OOP.
blitzmaster schrieb:
Ich muss aber auch sagen, dass nicht nicht unbediengt tollen und schön anzusehenden C++ Code schreiben möchte, sondern etwas, womit ich erreichen kann was ich will und vor allem auch wie ich es will.
Die Sache mit tollem und schön anzusehendem Code ist, dass man ihn schnell dazu bringt das zu tun was man will. Oder anders herum gesagt: Wenn man sich nicht ein wenig Zeit nimmt um den Code etwas übersichtlich, gut lesbar und simpel zu gestalten, dann verliert man das zehnfache der so gewonnenen Zeit, wenn man in dem unübersichtlichen, schwer zu lesenden Code rumwaten muss um die Stelle zu finden die dafür sorgt dass der Code nicht das tut was man will. Auch das ist eine der Stärken von C++: dass man lesbaren und leicht wartbaren Code schreiben kann - und in dem Fall hindert dich nichts dran diese Stärke auch zu nutzen.
-
pumuckl schrieb:
... und in dem Fall hindert dich nichts dran diese Stärke auch zu nutzen.
Doch, die fehlenden Runtime unterstützungen und die fehlende std die ich zuerst schreiben müsste.
Ich kann nicht die std schreiben, wenn mein OS nicht gewisse sachen unterstüzt. Doch um diese gewissen Sachen zu implementieren, muss ich auch irgendetwas machen, die wachsen leider nicht auf bäumen.... ERst wenn ich das habe, kann (und werde) ich mich auf die std stürzen.
Das mit dem schönen und tollen Code war wohl falsch ausgedrückt: Ich bin schon für lesbaren Code; aber ich bin dagegen, das ich nur weil es C++ ist, nicht auch C Methoden darin verwende (in begrenzten Maße natürlich, sonst wärs ja soweiso unnötig)
Das ich cout knicken kann, ist mir klar, und das "nur" war wohl auch falsch an der Stelle...Aber einen Kernel zu schreiben heißt mit NICHTS anzufangen. Man hat also absolut NICHTS zur Verfügung, außer die reinen OP Codes (oder wie auch immer das dann bei C++ heißt)
-
blitzmaster schrieb:
pumuckl schrieb:
... und in dem Fall hindert dich nichts dran diese Stärke auch zu nutzen.
Doch, die fehlenden Runtime unterstützungen und die fehlende std die ich zuerst schreiben müsste.
Ordentlicher Code braucht keine besonderen Runtime-unterstützungen.
-
Diese Sache mit den ostreams offensichtlich schon. Also kann ich das jetzt nicht machen.