C++ ungeeignet für 64K Demos?
-
Ist zwar ne 96K Demo, aber egal:
- .kkrieger is not written in 100% assembler/machine language. Not even nearly. Like the
vast majority of game projects being developed today, .kkrieger was mostly written in
C++, with some tiny bits of assembler where it is actually advantageous (notably, there
are a lot of MMX optimisations in the texture generator)..kkrieger war glaube ich der Gewinner der letztjährigen Breakpoint in der Kategorie 96K. Aber nicht drauf festnageln bitte

-
the_alien schrieb:
Aber er hat doch Recht diesmal.
Würde ich nicht sagen, wenn er eine 64KByte demo macht mit vielen Texteffekten, wäre ne std::string schon praktisch!
-
..................... schrieb:
@Volkard
Vielen dank! Hast du sonst noch paar Tips?nichts, was ich in ein paar sätzen aufschreiben könnte, füchte ich. und nix allgemeines.
aber vielleicht stellste einfach konkrete fragen, wenn du was vor hast, und dich fragst, wie man das am besten klein kriegt.doch noch was allgemeines. kein rtti. keine exceptions (eher keine fehlerbehandlung!). globalen op new überladen (gibt ja in der WinApi feinen ersatz). compileroptionen kennen. ich nehme an, exe-packer ind erlaubt? dann so einen auch nehmen.
aber bei 64k hat man so unheimlich viel platz für code, daß es gar nicht mehr am code liegt, sondern an den gafiken und models (generatoren nehmen, wenn möglich statt gepackter bitmaps ist wohl zur zeit in. ka, bin nicht in dieser szene daheim.).
-
Gut dann hab ich jetzt paar fragen:
- Wie sähe so ein überladener new-operator aus? Wieso sollte man den überhaupt überladen?
- Sollte man viel mit new arbeiten oder lieber statische-arrays schreiben? also char buffer[32];?
- Warum keine Exceptions?
- wie fängt man am beste für eine eigene string-klasse an? welche features sollten umbedingt rein und welche nicht?
-
..................... schrieb:
- Sollte man viel mit new arbeiten oder lieber statische-arrays schreiben? also char buffer[32];?
Statische Variablen sind schneller erstellt; derart kleine Arrays verursachen auch bestimmt keinen Stacküberlauf.
..................... schrieb:
- Warum keine Exceptions?
Weil die Überprüfung auf Exceptions deinen Code aufbläht.
-
audacia schrieb:
..................... schrieb:
- Sollte man viel mit new arbeiten oder lieber statische-arrays schreiben? also char buffer[32];?
Statische Variablen sind schneller erstellt; derart kleine Arrays verursachen auch bestimmt keinen Stacküberlauf.
Und wie ist das mit der größe?
Also ich glaube es gibt sicherlich einen unterschied in der größe der datei wenn ich:
char buffer[2048]; schreibe als
char *buffer = new char[2048];
-
..................... schrieb:
- Wie sähe so ein überladener new-operator aus?
void* operator new(size_t size){ return HeapAlloc(GetProcessHeap(),0,size); } void operator delete(void* p){ HeapFree(GetProcessHeap(),0,p); }Wieso sollte man den überhaupt überladen?
weil bei windows ein kleines speichermanagement eingebaut ist. es ist langsam und so, kein vergleich zum mitgelieferten operator new. aber es ist extrem wenig code für's eigene programm.
- Sollte man viel mit new arbeiten oder lieber statische-arrays schreiben? also char buffer[32];?
statische arrays sind noch billiger. zum freigeben braucht man gar keinen code und zum anlegen muß nur der stackpointer inkrementiert werden. außerdem werden statische arrays viel schneller angelegt.
aber was ist, wenn man die größe nicht zur compilezeit kennt oder wenn man innerhalb einer funktion speicher anlegen möchte und den speicher zurückgebenb will? da muß schon new her.- Warum keine Exceptions?
das exception-handling macht beim MinGW schon allein 20k aus. das kann sich natürlich keiner leisten. ok, mal alternativen angucken.
a) kleineres exception-handlich schreiben.
ist sehr schwirig, weil a viel compilermagie dabei ist
b) das in den microsoft-dlls benutzen
keine ahnung, ob das erlaubt ist. ich vermute mal: nein.
c) fehler wie gewohnt in c hochgeben.
naja, bei mini-programmen ist das billiger als exception-handling. bei fetteren programmen wird dann das exception-handling billiger.
d) einfach alle fehler ignorieren!
yeah, that's it! wenn der user keine soundkarte hat oder directx nicht hat, kackt das prog einfach ab. das scheint mir ideal für 64k-demos.- wie fängt man am beste für eine eigene string-klasse an?
so:
class String{ char* date; public: String(char const* d=""){ data=new char[strlen(d)+1]; strcpy(d,data); } }welche features sollten umbedingt rein und welche nicht?
je nach dem, was die anwendung machen soll. strings könnten zum beispiel welche sein, die keinen besitz am speicher haben
class String{ char const* date; public: String(char const* d=""){ data=d; } friend bool operator==(string const a,string const b){ return strcmp(a.data,b.data)==0; } }und die nur dafür sorgen, daß man mit char* ein wenig leichter umgehen kann und einen eigenen namen hat. das wäre zunächst mein weg, denn ich fürchte, außer ein paar dateinamen und so würden strings nicht viel verwendet werden. und wieder der vorteil, ich kann auch ganz am ende, wenn ich feststelle, daß ich doch andere strings hätte nehmen sollen, sie an einer zentralken stelle (der String.cp) verändern und das ganze programm hat was davon.
sie könnten auch wie die klasse zuvor sich immer eine kopie der daten machen und dann konsequenterweise im destruktor die kopie löschen. sie könnten auch in einer globalen hashtable ihre daten eintragen und nur indizes auf die hashtable führen.
-
@volkard
Vielen Dank! Doch noch eine frage zur string-klasse: Du initialisierst mit new, aber gibst den speicher nicht mehr frei? Also das du von Fehlerbehandlung in 64K-Demos nichts hälst hast du ja erklärt aber Fehlermachung? :D:D:D
-
@.........................:
Deine Frage war:
.............. schrieb:
- wie fängt man am beste für eine eigene string-klasse an?
, und genau darauf hat Volkard geantwortet.
-
audacia schrieb:
@.........................:
Deine Frage war:
.............. schrieb:
- wie fängt man am beste für eine eigene string-klasse an?
, und genau darauf hat Volkard geantwortet.
Das ist doch kein Argument etwas anzufangen und halb fertig liegen lassen. Das ist eine Potenzielle Fehlerquelle!
-
.................. schrieb:
Das ist doch kein Argument etwas anzufangen und halb fertig liegen lassen. Das ist eine Potenzielle Fehlerquelle!
erhoffst du dir, daß ich eine fertige string-klasse baue? dazu hatte ich gerade keine lust.
-
volkard schrieb:
weil bei windows ein kleines speichermanagement eingebaut ist. es ist langsam und so, kein vergleich zum mitgelieferten operator new. aber es ist extrem wenig code für's eigene programm.
Das mitgelieferte new ruft über Umwege schon HeapAlloc auf.
volkard schrieb:
statische arrays sind noch billiger. zum freigeben braucht man gar keinen code und zum anlegen muß nur der stackpointer inkrementiert werden. außerdem werden statische arrays viel schneller angelegt.
Statische Arrays beeinflussen den Stackpointer nicht. Das Anlegen geschieht, bevor main aufgerufen wird
-
vollkard schrieb:
Das mitgelieferte new ruft über Umwege schon HeapAlloc auf.
oder besser VirtualAlloc. mir geht es darum, die umwege wegzumachen. die umwege sind zum beispiel ein small object allocator, den man in c++ sinnvollerweise davorsetzt, um mehr speed zu bekommen. siehe modern c++ design. in der 64k-demo spare ich mir einfach den ganzen speed-bringenden umweg und mache ein lahmes, aber kleines new.
vollkard schrieb:
Statische Arrays beeinflussen den Stackpointer nicht. Das Anlegen geschieht, bevor main aufgerufen wird
"statisch" hat mehr als eine bedeutung, scheint mir. ich meinte hier nur statisch im gegensatz zu dynamisch. mit dynamisch bezeichnet man speicher, den man sich zur laufzeit über aufrufe von new, malloc und so holt und dessen größe duchaus erst zur laufzeit bekannt sein kann. mit statisch bezeichnet man speicher, der per definition da ist, dessen größe erst zur compilezeit bekannt ist.
in diesem sinne ist ein lokales array durchaus statisch.du scheinst das schlüsselwort static zu meinen. also im prinzip globalen variablen. der ist in der tat noch billiger, was die code-größe angeht.
-
@TGGC_work
ich erteile dir hiermit virtuelles hausverbot für diesen thread. du darfst hier nicht mehr posten.
ich logge, wie oft ich postings von dir lösche und behalte mir vor, dich bei zuwiderhandlung kostenpflichtig abzumahnen.
-
volkard schrieb:
@TGGC_work
ich erteile dir hiermit virtuelles hausverbot für diesen thread. du darfst hier nicht mehr posten.
ich logge, wie oft ich postings von dir lösche und behalte mir vor, dich bei zuwiderhandlung kostenpflichtig abzumahnen.Gilt das für alle TGGC's?
Bye, TGGC (Wähle deine Helden)
-
TGGC´ schrieb:
Gilt das für alle TGGC's?
Es gilt für alle, die, obwohl ich ein Posting gelöscht habe, es wieder einstellen. Im Falle dieses Störers dürften es an die 100 Löschungen schon sein. Und natürliche bedarf es keiner Warnung, bevor ich rechliche Schritte einleite, aber ich hoffe, er hört auf, ohne daß ich ganz fies werden muß.
-
volkard schrieb:
.................. schrieb:
Das ist doch kein Argument etwas anzufangen und halb fertig liegen lassen. Das ist eine Potenzielle Fehlerquelle!
erhoffst du dir, daß ich eine fertige string-klasse baue? dazu hatte ich gerade keine lust.
Das brauchst du auch nicht, mein Süßer. Das mach' ich schon für dich:
#include <iostream> #include <cstring> using namespace std; class String { public: // Konstruktoren String(); String(const char *const); String(const String &); ~String(); // Überladene Operatoren char & operator[](int offset); char operator[](int offset) const; String operator+(const String&); void operator+=(const String&); String & operator= (const String &); // Allgemeine Zugriffsoperatoren int GetLen()const { return itsLen; } const char * GetString() const { return itsString; } // static int ConstructorCount; private: String (int); // Privater Konstruktor char * itsString; int itsLen; }; // Standardkonstruktor erzeugt String von 0 Bytes Länge String::String() { itsString = new char[1]; itsString[0] = '\0'; itsLen=0; // cout << "\tString-Standardkonstruktor\n"; // ConstructorCount++; } // Privater (Hilfs-) Konstruktor, nur von Klassen- // methoden zum Erzeugen eines neuen Strings der // erforderlichen Größe verwendet. Mit Null gefüllt. String::String(int len) { itsString = new char[len+1]; int i; for (i = 0; i<=len; i++) itsString[i] = '\0'; itsLen=len; // cout << "\tString(int)-Konstruktor \n"; // ConstructorCount++; } String::String(const char * const cString) { itsLen = strlen(cString); itsString = new char[itsLen+1]; int i; for (i = 0; i<itsLen; i++) itsString[i] = cString[i]; itsString[itsLen]='\0'; // cout << "\tString(char*)-Konstruktor\n"; // ConstructorCount++; } String::String (const String & rhs) { itsLen=rhs.GetLen(); itsString = new char[itsLen+1]; int i; for ( i = 0; i<itsLen;i++) itsString[i] = rhs[i]; itsString[itsLen] = '\0'; // cout << "\tString(String&)-Konstruktor\n"; // ConstructorCount++; } String::~String () { delete [] itsString; itsLen = 0; // cout << "\tString-Destruktor\n"; } // Gleich-Operator, gibt vorhandenen Speicher frei, // kopiert dann String und Größe String& String::operator=(const String & rhs) { if (this == &rhs) return *this; delete [] itsString; itsLen=rhs.GetLen(); itsString = new char[itsLen+1]; int i; for (i = 0; i<itsLen;i++) itsString[i] = rhs[i]; itsString[itsLen] = '\0'; return *this; // cout << "\tString-Operator=\n"; } // Nicht konstanter Offset-Operator, gibt Referenz // auf Zeichen zurück, das sich damit ändern // läßt! char & String::operator[](int offset) { if (offset > itsLen) return itsString[itsLen-1]; else return itsString[offset]; } // Konstanter Offset-Operator für konstante // Objekte (siehe Kopierkonstruktor!) char String::operator[](int offset) const { if (offset > itsLen) return itsString[itsLen-1]; else return itsString[offset]; } // Erzeugt einen neuen String durch Anfügen des // aktuellen Strings an rhs String String::operator+(const String& rhs) { int totalLen = itsLen + rhs.GetLen(); int i,j; String temp(totalLen); for (i = 0; i<itsLen; i++) temp[i] = itsString[i]; for (j = 0; j<rhs.GetLen(); j++, i++) temp[i] = rhs[j]; temp[totalLen]='\0'; return temp; } // Ändert aktuellen String, gibt nichts zurück void String::operator+=(const String& rhs) { int rhsLen = rhs.GetLen(); int totalLen = itsLen + rhsLen; int i,j; String temp(totalLen); for (i = 0; i<itsLen; i++) temp[i] = itsString[i]; for (j = 0; j<rhs.GetLen(); j++, i++) temp[i] = rhs[i-itsLen]; temp[totalLen]='\0'; *this = temp; } // int String::ConstructorCount = 0;
-
bei mir bringt der überladene new operator weder vor noch nach dem upx'en etwas.

wobei ich für meine kleinen 64k demos bisher nie new benutzte und stringklassen emm.. naja... emm... wozu strings? hab ich auch noch nie benutzt.btw. sind bei 64k demos externe system-dlls die jeder haben sollte erlaubt, sonst wäre dx und oGL auch nicht zugelassen

rapso->greets();
-
volkard schrieb:
und wie sehen diese template-tricks aus?
schattig. du mußt halt genau wissen, was du machst (auch immer wieder den erzeugten asm-code angucken, um ein gefühl dafür zu kriegen, was der compiler draus macht).
Oh, da hab ich mich ein wenig vertan. Template-Tricks helfen ja eher Binarygröße für Speed einzutauschen durch Loopunrolling und Inlining. Naja, da muss man wohl mal ein wenig rumtesten, was man damit rausholen kann.
-
ich seh trotzdem nicht, was compileroptionen wie loop unrolling und sprachmerkmale wie "inline" mit c++ templates zu tun haben sollen...
die stringklasse war sehr lehrreich. ich werd sie mir auch mal zerlegen und untersuchen.