[solved] struct-Name per Laufzeit erstellen

Posted By: JoGa

[solved] struct-Name per Laufzeit erstellen - 09/16/11 15:48

Hey

Ich hab wiedermal ein Problem, an dem ich jetzt schon den Nachmittag knabbere und nicht drauf komme:

Ich hab ein struct angelegt, mit dem ich die Gegenstände verwalten kann, die in meinem Spiel anfallen.
Das Struct "Gegenstand" habe ich mit verschiedenen Pointern, wie zum Beispiel Gegenstand.kosten als int oder Gegenstand.Beschreibung als string.

Nun sollen Gegenstände mit einem Algorythmus generiert werden. Die "Eigenschaften" der Gegenstände sollen zufällig sein.
zB. zufällige Kosten.
Das macht mir keine Probleme, doch müsste ich die Gegenstände ja vorher mit einem Namen "deklarieren"(?).
Dh. ich muss den programminternen Namen generieren und dann die Pointer/Gegenstände durch den Struct initialisieren:

Gegenstand* xyz = {...}

Wie kann ich jetzt den Namen "xyz" des Gegenstandes per Laufzeit festlegen? Als string geht nicht, hab ich schon versucht.
Posted By: ventilator

Re: [solved] struct-Name per Laufzeit erstellen - 09/16/11 16:21

sowas funktioniert nur in dynamischen sprachen wie z.b. python.

in c musst du das anders lösen. ich würde den namen im struct speichern, die structs in einem array (oder einer liste) ablegen und darauf mit einer funktion wie get_struct("xyz") zugreifen.
Posted By: JoGa

Re: [solved] struct-Name per Laufzeit erstellen - 09/16/11 17:42

hm, okay, schade.
Aber vielen Dank für deine Erläuterung. Jedoch ist mir dann nicht klar, wie ich die structs dann per Laufzeit benennen kann, da ja wärend dem Spiel immer wieder neue erstellt werden, dessen Namen ich beim Programmieren ja selbst noch nicht kenne.

Da muss ich noch etwas darüber grübeln ^^
Posted By: TechMuc

Re: [solved] struct-Name per Laufzeit erstellen - 09/16/11 19:19

versteh gar nicht was du willst laugh

Füg doch einfach ein attribut hinzu.

Code:
sruct object
{
   STRING* name;
   //...
};

function create_random_object()
{
  object* obj  = malloc(sizeof(object));
  obj->name = str_create("#512");
  str_cpy(obj->name,_str("test"));
}



Oder was willst du wirklich erreichen?
Posted By: HeelX

Re: [solved] struct-Name per Laufzeit erstellen - 09/16/11 20:11

@TechMuc: in deiner Methode solltest du das Objekt auch zurückgeben sonst kann da ja keiner zugreifen wink

@JaGo: Also generell würde ich dir ans Herz legen, eine verkettete Liste anzulegen, die zur Verwaltung deiner Objekte eingesetzt wird. Eine verkettete Liste deshalb, weil du ja beliebig viele haben willst. Dann erzeugst du, wie TechMuc zeigte, deine Objekte und speicherst in einem String den Namen des Objektes. Dann, wenn du drauf zugreifen willst, gehst du durch deine verkettete Liste, überprüfst den String des Objektes, das du haben willst, mit jedem Objekt-String und dann irgendwann bist du entweder durch und hast nix gefunden oder das Objekt, dass du wolltest.

Das wars dann auch schon! Oder??
Posted By: TechMuc

Re: [solved] struct-Name per Laufzeit erstellen - 09/16/11 20:23

Ja ehrlich gesagt, bin ich nur einfach ziemlich irritiert von der Antwort von Ventilator, und noch mehr irritiert von der Frage grin
Posted By: JoGa

Re: [solved] struct-Name per Laufzeit erstellen - 09/16/11 20:33

das mit der verketteten Liste ist ein gutes Stichwort, da werd ich mich morgen einlesen. Vielen Dank!

@Techmuc: Mein Problem ist, dass ich nicht verstehe, wie ich vorgehen soll, wenn ich mehrere zufällig generierte Objekte habe, de ich handhaben muss.
Stell dir vor, der Spieler öffnet eine Truhe und es fallen 5 zufällig generierte Objekte raus - dann hab ich ja nach deinem Beispiel 5 mal den Pointer "obj"?
Das ist das, was mir nicht in die Gehirnwindungen will, wie ich die Pointer dann unterscheiden kann.
Posted By: ventilator

Re: [solved] struct-Name per Laufzeit erstellen - 09/16/11 20:42

Originally Posted By: TechMuc
Ja ehrlich gesagt, bin ich nur einfach ziemlich irritiert von der Antwort von Ventilator, und noch mehr irritiert von der Frage grin
wieso? ich hab genau das gleiche gemeint wie heelx. laugh nur weniger detailiert erklärt...

Quote:
sowas funktioniert nur in dynamischen sprachen wie z.b. python.
damit hab ich nur gemeint, dass in dynamischen sprachen strings verwendet werden können um objekte zu erzeugen oder darauf zuzugreifen. sinn machen tut das aber eh selten...
Posted By: TechMuc

Re: [solved] struct-Name per Laufzeit erstellen - 09/16/11 20:46

Hallo Joga,

Okay ich verstehe deine Gehirnwindungen noch nicht so ganz, aber wir kommen der Sache näher wink
Wenn du eine Kiste hast, aus der kommen 5 Entites raus wird deine Struktur ja vermutlich in etwa so aussehen:

Code:
struct Object {
  ENTITY* p_entity; //entity pointer
  //weitere daten
};



Für jedes Objekt aus der Truhe muss mindestens ein Alloc Befehl ausgeführt werden. Beispiel:

Code:
Object* obj = malloc(sizeof(Object));
obj->p_data = ent_create(...);
obj->weitere_daten = ...;



Das Objekt exisitiert jetzt erstmal und its direkt mit dem Entity verbunden. Kannst dann per typecast darauf zugreifen.. E.g.

Code:
//get object of entity
Object* p_data = (Object*)(ENTITY*)any_ent;



Und so weitere daten aus der Struktur ziehen. Achtung: Das geht nur weil "ENTITY" an erster stelle in der Struktur steht...

so jetzt verstehe ich immer noch nicht so ganz genau was deine Frage ist laugh

Quote:
Das ist das, was mir nicht in die Gehirnwindungen will, wie ich die Pointer dann unterscheiden kann.

Die Pointer unterscheidest du, indem die Pointer unterschiedliche Werte haben und auf unterschiedliche Objekte zeigen. Diese Objekte können dann natürlich auch unterschiedliche Werte haben.

Wenn du außerhalb von bestimmten Events (wie z.B. mausklick o.ä.) auf die Entities zugreifen willst, musst du die Struktur noch in einem Container abspeichern (wie vorher angesprochen von HeelX in einer Liste, in einem Vektor oder was auch immer).

Weitere Unklarheiten,
Her damit..

Gruß,
Timo
Posted By: JoGa

Re: [solved] struct-Name per Laufzeit erstellen - 09/17/11 15:09

So, vielen Dank für die detailierte Erklärung, das ist wirklich sehr lieb.
Ich habe in einem C++-Buch, das schon ewig ungelesen in meinem Schrnak steht etwas über structs erfahren wollen, aber da stand nicht viel drin, da sind wohl zwei "+" zu viel im Titel laugh
Mal in der Unibibo schaun, wenn ich wieder am Studienort bin.
toller Workshop von HeelX hab ich noch gefunden, da werden auch structs etwas behandelt, das werde ich mir, sobald mein Besuch gekommen und wieder abgezischt ist, zu Gemüte führen ;-)

Tut mir leid, dass ich das Forum zu zumülle, aber ich hab noch ein paar Verständnissfragen tongue

- Wenn aus der Kiste (sagen wir mal) 5 Tomaten fallen, dann erzeuge ich ja diese mit hilfe des structs:
Objekt* Tomate = malloc(sizeof(Object));
// und dann die einzelnen Daten zuweisen
und mein Gehirnwindungsproblem ist jetzt, dass ich 5 "virtuelle" Objekte habe, die aber alle den selben Pointer "Tomate" haben. Und das beisst sich bei mir im Kopf mit dem pointer "player", der ja nur auf ein Entity gesetzt werden kann. Soweit ich das jetzt verstanden habe, sind das ja aber 2 Paar Stiefel (Struct-Pointer und Entity-Pointer).
Doch per structs lassen sich doch neue Engine-objekte (wie z.B Strings) erstellen - und 2 gleiche stringnamen sind ja auch nicht möglich - warum also bei denn Ojekten "Tomate"?

- zweites Problem:
Quote:
Wenn du außerhalb von bestimmten Events (wie z.B. mausklick o.ä.) auf die Entities zugreifen willst, musst du die Struktur noch in einem Container abspeichern (wie vorher angesprochen von HeelX in einer Liste, in einem Vektor oder was auch immer).

Nehmen wir an, der Spieler klickt auf eine Tomate nach der anderen, um sie in sein Obstkörbchen zu packen.
Kann ich da so herangehen, dass ich ein Variable "Maus_gegenstands_ID" erstelle.
Wenn nun der Spieler auf eine Tomate klickt, sucht sie in ihrem Klick-Event in dieser verketteten Liste nach ihrem Struct und kopiert dann die ID-Nummer des Objektes (die beim Truhenöffnen den einzelnen Tomaten per Zufall zugewiesen wurde) in die Variable "Maus_gegenstands_ID".
Wenn nun der Spieler in einen seiner Obstkörbchenplätze klickt, wird diese Nummer in ein Array kopiert, der das Obstkörpchen repräsentiert.
Würde das so funktionieren?

Ich habe mir heute mittag bei der Gartenarbeit eine andere Variante überlegt: Der Gegenstand wird durch eine ID-Nummer repräsentiert.
jede Eigenschaft des Objektes entspricht einer oder mehreren Dezimalstellen. Per if-Anweisungen wird dann die ID zerlegt und nachgeschaut z.B. welche Nummer bei der Dezimalen für das Modell steht - entsprechend der Nummer wird dann das jeweilige Modell erstellt. Eine andere Nummer steht für das 2D-Sprite im Inventar. Eine andere Nummer für den minimalen Schaden, eine andere für den maximalen Schaden, ...
Da die Gegenstände etwas komplexer sind, komme ich auf 16-18 Dezimalstellen. Ich habe aber das Gefühl, dass diese Variante von Vorgestern ist, denn: Sie würde funktionieren, ist aber ziemlich aufwenig, wenn man sich die Menge an Schreibarbeit vorstellt, die benötigt wird, um die einzelnen Nummern in if-Abfragen den versch. Modellen, Sprites, Eigenschaften der Objekten zuzuweisen.
Da du die struct-Sachen ja recht gut durchschaust, könntest du mir vielleicht einen Tipp geben, welche Variante die geschicktere wäre?
Posted By: TechMuc

Re: [solved] struct-Name per Laufzeit erstellen - 09/17/11 17:37

Ich hole im weiteren Post sehr weit aus - wenn du verschiedene Sachen schon weißt - sorry for that.

Quote:
Mein Gehirnwindungsproblem ist jetzt, dass ich 5 "virtuelle" Objekte habe, die aber alle den selben Pointer "Tomate" haben. Und das beisst sich bei mir im Kopf mit dem pointer "player", der ja nur auf ein Entity gesetzt werden kann. Soweit ich das jetzt verstanden habe, sind das ja aber 2 Paar Stiefel (Struct-Pointer und Entity-Pointer).
Doch per structs lassen sich doch neue Engine-objekte (wie z.B Strings) erstellen - und 2 gleiche stringnamen sind ja auch nicht möglich - warum also bei denn Ojekten "Tomate"?


Denke nicht so realistisch. Denke in Bytes.. ist einfacher wink
Erstmal: Was macht der Befehl malloc? Dazu mal ein stark vereinfachtes Beispiel:
Code:
for(int i=0;i<5;i++) {
  Object* obj = malloc(sizeof(Object));
  //more code
}


Sagen wir mal wir leben vor 20 Jahren wo du in deinem Prozess nur 256 Bytes an RAM hattest - Ist leichter darzustellen. Am Anfang ist der ganze RAM frei (vor der ersten malloc anweisung). Nun führst du den Befehl "malloc(sizeof(OBJECT));" aus, was ja für den PC nichts anderes ist als z.B. malloc(80);. Jetzt wird der PC den Speicher durchsuchen, wo noch 80 Bytes frei sind. Findet er, da noch alles direkt frei ist natürlich an erster Stelle. Sagen wir dein Prozess hat Speicherzugriff ab der RAM Position 0x1, dann wird die malloc Anweisung 0x1 zurück liefern.

Nach der erstmaligen Ausführung des Befehls:
Object* obj = malloc(sizeof(Object));
Hat die Variable obj also den Wert 0x1, wobei obj auf einen Speicherbereich zeigt der 80 Byte groß ist (s. Behauptung oben, dass sizeof(object) = 80).

Nun wird die Schleife durchlaufen, und du kommst wieder zu den malloc Befehl. Der PC durchsucht den RAM wieder und erkennt, dass an Stelle "0x1" ein Objekt angelegt ist mit der Größe 80. Daher kann er hier nichts ablegen und springt da rüber. Kommt raus an Stelle 0x51h (Hexadezimal.. Dezimal 81). Hier erkennt er, dass das frei ist. D.h. malloc registriert jetzt an dem PC: "Ab jetzt wird die Speicherstelle 0x51h - 0XA1h nicht mehr vergeben".
Malloc liefert also 0x51h zurück. Das heißt:

Nach der zweiten Ausführung des Befehls:
Object* obj = malloc(sizeof(Object));
hat obj jetzt den Wert 0x51h.

Das heißt: Für den PC ist das alte "Object" etwas völlig anderes als das neue "Object". Das eine ist was 80 Byte großes was an Position 0x1 liegt, das andere ist was 80 Byte großes was an Position 0x51h liegt. Mehr weiß der PC nicht und mehr will er auch nicht wissen laugh
Für dich heißt das: Wenn du mit den Objekten kommunizieren willst (also auf diese angelegten Objekte zugreifen willst), musst du dir genau diese Zahl merken (0x1h oder 0x51h).
Dies führt auch dazu, dass du dir irgendwie merken musst, dass du da an Stelle 0x1 und 0x51 ein Objekt angelegt hast - wenn du dir das nicht merkst sind diese Daten verloren und du hast ein Memory leak produziert (wie sollst du dem PC sagen, dass du die Daten nicht mehr brauchst - also wie gibst du die Daten per "free" frei - wenn du dir nicht gemerkt hast wo sie liegen?).

So weiter im Text. Wenn ich dich richtig verstehe meinst du so einen Code:
Code:
struct Object {
   ENTITY* ent;
   STRING* name;
};
Objekt* Tomate = malloc(sizeof(Object));
Tomate->ent = ent_create("..."....);
Tomate = malloc(sizeof(Object));
Tomate->ent = ent_create("...")...);
Tomate = malloc(sizeof(Object));
//..



Hier hast du jetzt 3x ein objekt Tomate angelegt. Ich mach mal mit meinen Byte Positionen von oben weiter.
Das erste Objekt wird an Position 0x1 erstellt. Nun greifst du auf Object->Ent zu. Was passiert jetzt intern? Der PC versucht das natürlich irgendwie zu verstehen und auf Byteebene runterzurechnen. Also der PC weiß, dass er "Tomate" an Stelle 0x1 liegt. Nun muss er nur noch wissen, was für einen Offset "Ent" innerhalb des Objektes "Tomate" hat, und welche Größe "Ent" hat. Der Offset ist, da "Ent" an erster Stelle liegt: 0. Die Größe von Ent ist 4 (da es ein Pointer ist) ==> Der PC weiß: Ich überschreibe jetzt Speicherbereich 0x1 - 0x5 mit dem Wert der von der Funktion ent_create zurückgeliefert wird.

Wenn du nun malloc nochmal Aufrufst und wieder im Objekt "Tomate" speicherst hast du die alte Speicherposition verloren. Du kommst da auch nie wieder hin, außer du hast wirklich nur 256 Byte RAM laugh
Das ist der Grund warum das Objekt Tomate speichern musst. Hier mal der Beispielscode einer verketten Liste für sowas:

Code:
struct object {
  ENTITY* ent;
  object* next;
  object* prev;
};

object* current_head = 0;
object* current_tail = 0;

int object_create(STRNG* str, VECTOR vpos, EVENT evt) {
  object* obj = malloc(sizeof(object));
  if(!current_head) {
    current_head = obj;
    current_tail = obj;
    obj->next = 0;
    obj->prev = 0;
  }
  else {
    current_tail->next = obj;
    obj->next = 0;
    obj->prev = current_tail;
    current_tail = obj;
  }
  obj->ent = ent_create(str,vpos,evt);
  return obj;
}

//BEIM LÖSCHEN MUSS DAS WIEDER AUS DER VERKETTEN LISTE RAUS!




Wenn du jetzt via object_create ein Objekt erschaffst, kann keiner der vielen Pointer mehr verschwinden, da sie alle in der verketten liste abgelegt sind.

Und nochmal ganz wichtig: Der Name eines Objektes interessiert den PC kein Stück. Ob du jetzt Object* tomate oder Object* blabber; schreibst. Der PC weiß nur, dass es ein 4 Byte großer Pointer ist der irgendwo im RAM liegt.

Quote:
Nehmen wir an, der Spieler klickt auf eine Tomate nach der anderen, um sie in sein Obstkörbchen zu packen.
Kann ich da so herangehen, dass ich ein Variable "Maus_gegenstands_ID" erstelle.
Wenn nun der Spieler auf eine Tomate klickt, sucht sie in ihrem Klick-Event in dieser verketteten Liste nach ihrem Struct und kopiert dann die ID-Nummer des Objektes (die beim Truhenöffnen den einzelnen Tomaten per Zufall zugewiesen wurde) in die Variable "Maus_gegenstands_ID".


ID würde ich nicht machen, da recht langsam. Generell würde ich empfehlen, einen Pointer auf die "Object" Struktur in einem Skill abzuspeichern.
Das ist vieeel schneller als das traversieren durch die verkette Liste.
Beispiel hierfür:

Code:
struct object {
  ENTITY* ent;
  //weitere daten
};

int object_create(STRNG* str, VECTOR vpos, EVENT evt) {
   object* obj = malloc(sizeof(Object*));
   obj->ent = ent_create(str,vpos,evt),
   obj->ent->skill[99] = (int)(void*)obj;
   return obj;
}

int object_delete(ENTITY* ent) {
   if(ent->skill[99]) {
     object* obj = (object*)ent->skill[99];
     free(obj);
   }
   ent_remove(ent),
   return 0;
}



Das ist die schnellste Lösung. Das Problem ist, dass du hier dafür veranwortlich bist, dass am Ende alle Entities von DIR gelöscht werden (via object_remove) und nicht mit ptr_remove/ent_remove oder von der engine bei einem neuen level_load.

Kurz zu erläuterung: Beim anlegen des Objektes wird das Objekt wieder an Speicherposition 0x1 erschaffen. Diese Speicherposition ist wie bei allen 32 bit Anwendungen exakt 4 Byte groß. Ein Skill ist auch exakt 4 Byte groß (so ist "var" definiert, und ein skill ist ja vom Typ var). Das heißt du kannst den Pointer zu dem Objekt, statt in einer verketten liste auch einfach in dem Skill abspeichern. Lass dich nicht dadurch irritieren, dass du einen Skill vll. nicht als Pointerspeicher kennst. Für den PC ist ein Skill exakt 4 Byte groß, der Pointer ist 4 Byte groß - passt - also kann der Pointer in den Skill rein. Fertig für den PC.
Den Compiler musst du noch "überzeugen", dass das wirklich geht, daher die Typecasting Anweisungen. Ohne Typecasten würde der Compiler (vermutlich) sagen: "Ne, (Object*) ist nicht das gleiche wie (var) - mach ich nicht mit". Mit dem Typecasten zwingst du dem Compiler zu akzeptieren, dass (Object*) eigentlich ja das gleiche wie ein (var) ist und speicherst das Objekt in dem Skill.

Dadurch ist der Pointer nicht verloren gegangen (auch wenn du ihn nicht in einer liste o.ä. abspeicherst) und du hast weiter Zugriff druff ==> Kein Memory Leak Produziert. Passt.


So kA.. so viel geschrieben und weiß nicht ob das alles sinnvoll ist. Naja stimmen sollte es (auch wenn die Deutsche Sprache vermutlich nicht so toll ist wink )
Posted By: JoGa

Re: [solved] struct-Name per Laufzeit erstellen - 09/18/11 18:51

Hey

vielen Dank für deine rießige Erklärung, sie hat mir sehr viel geholfen.
2 Fragen habe ich noch :-/
In deinem Beispiel hast du die Datenposition in einem Skill gespeichert:
Code:
obj->ent->skill[99] = (int)(void*)obj;


und später wieder ausgelesen:
Code:
object* obj = (object*)ent->skill[99];


1. Frage: Warum benötigt man das "void"? Das int erscheint mir nach deiner Erklärung logisch, doch das "void" kann ich mir nicht erklären (was es bedeutet [Funktionstyp ohne Rückgabewert] weis ich einiger maßen), doch verstehe ich die Bedeutung in deinem Kontext nicht.
2. Frage: Ich habe nach deinem Beispiel versucht, mir ein Gegenstand zu programmieren, den ich anklicken kann und dann eine gespeicherte bmp-Datei aus dem Struct heraus zu laden. Es erzeugt aber ein script-crash:SYS und ich bin mir nicht sicher, was ich bei der Zuweisung falsch gemacht habe:

Der Fehler liegt im Event. Es läuft alles rund, solang ich die Zeile
Code:
pan_mausitem.bmap = fallengelassener_gegenstand.inventar_bild;

auskommentiert habe. Also müsste die Zuweisung auf "fallengelassener_gegenstand" im Event nicht richtig sein, aber da bin ich mit meinem Latein am Ende.

Code:
typedef struct
{
	ENTITY* ent_entity;	// der Entitypointer auf das Objekt im 3D-Raum, das gedroppt wurde
	BMAP* inventar_bild;
}gegenstand;

function testGegenstand_event()
{
	gegenstand* fallengelassener_gegenstand = (gegenstand*)my->skill[99];
	pan_mausitem.bmap = fallengelassener_gegenstand.inventar_bild;
}
function testGegenstand()
{
	while(enet_ent_globpointer(my) == ANET_ERROR) {wait(1);}
	my.event = testGegenstand_event;
	my.emask |= ENABLE_CLICK;
	while(1) {my.pan += 3 * time_step; wait(1);}
}

function gegenstandstest()
{
	while(key_f==0){wait(1);} while(key_f){wait(1);}
	
	gegenstand* fallengelassener_gegenstand = malloc(sizeof(gegenstand));
	fallengelassener_gegenstand->ent_entity = enet_ent_create("temp_ent.mdl",vector(random(300),random(300),0),"testGegenstand");
	fallengelassener_gegenstand->inventar_bild = "pct_item_testgegenstand.tga";
	fallengelassener_gegenstand->ent_entity.skill[99] = (int)(void*)fallengelassener_gegenstand;
}


Posted By: TechMuc

Re: [solved] struct-Name per Laufzeit erstellen - 09/18/11 19:36

Hey,

Quote:
1. Frage: Warum benötigt man das "void"? Das int erscheint mir nach deiner Erklärung logisch, doch das "void" kann ich mir nicht erklären (was es bedeutet [Funktionstyp ohne Rückgabewert] weis ich einiger maßen), doch verstehe ich die Bedeutung in deinem Kontext nicht.

Generell sollte das void* unnötig sein, verdeutlicht aber den typecasting vorgang.
Für einen Compiler ist void ein synonym für "unbekannt". Das heißt das ein Zeiger auf "unbekannt" auf jeden beliebigen Datensatz, beliebiger Größe zeigen kann. Warum schreibe ich das hier dazu? Wenn du schreibst:
ent->skill[0] = (var)pointer;
Können bestimmte Compiler auf die Idee kommen zu sagen, dass das so wohl nicht stimmt. Weil: Ein Pointer ist erstmal kein var. Nun sucht der Compiler ob er einen Pointer in eine var automatisch umrechnen kann. Hier gibt es jetzt drei Ergebnismöglichkeiten:
1) Er erkennt, das var größe = pointer größe und schreibt den Pointer 1:1 in ent->skill[0] - gut!
2) Er kennt keine Regel um einen Pointer in eine var zu schreiben und gibt einen Syntaxfehler aus (in die Richtugn: No conversion defined between var and ENTITY*).
3) Er kennt eine Regel die aber falsch ist bzw. hier nicht passt und schreibt einen falschen Wert in ent->skill[0].

Um alle Probleme zu vermeiden typecaste ich hier zweimal (wie gesagt, vermutlich NICHT notwendig). Als erstes wird dem Compiler mitgeteilt, dass die ENTITY* Struktur in echt ein Pointer auf etwas unbekanntes ist (void*). Der Compiler "vergisst" also, was an der Stelle von ENTITY* hinzeigt überhaupt steht. Für den compiler ist das jetzt wirklich nur noch n Zeiger auf einen unbekannten Wert. Danach kommts zu einem typecast zu (int). Das akzeptiert der Compiler ganz sicher (und schreibt exakt die 4 bytes des pointers in die var), da er ja gar nicht weiß was (void*) eig ist.. daher kann er auch keine falschen Regeln anwenden bzw. motzen..


Zu deinem Code:
1) genau so wirds gemacht
2) fallengelassener_gegenstand->inventar_bild = "pct_item_testgegenstand.tga";
ist falsch.

Code:
fallengelassener_gegenstand->inventar_bild = bmap_create("pct_item_testgegenstand.tga");



ist richtig..
Posted By: TechMuc

Re: [solved] struct-Name per Laufzeit erstellen - 09/18/11 19:38

Wobei du hier übrigens wieder siehst wie behindert der Lite-C Compiler ist.

Zu versuchen einen Character String ("blbla") einen pointer zuzuweisen darf niemals ohne fehlermeldung durchgehen.. Naja egal..
Posted By: JoGa

Re: [solved] struct-Name per Laufzeit erstellen - 09/18/11 20:34

Vielen Dank für deine Erklärungen!
Woher weist du das? Hast du schon selbst einen Compiler programmiert oder aus welchem Buch hast du das alles gelernt?
Auf jeden Fall vielen Dank für deine Mühe und Zeit, die du dir nimmst!

Deine Verbesserung leuchtet mir ein - hab ich in den bmap* Pointer ja einfach nur einen Dateinamen einspeichern wollen.
bmap_create gibt einen Pointer, daher muss ich das nehmen.
Aber leider wird mir trotzdem ein script-crash präsentiert, sobald die event-Funktion aufgerufen wird.
Ich habe nach dem Motto "Jugend forscht"
Code:
pan_mausitem.bmap = (BMAP*)fallengelassener_gegenstand.inventar_bild;

sicherheitshalber das (BMAP*) noch hinzugefügt, jedoch ohne daraus resultierende Verbesserung. Der Crash passiert trotzdem.

pan_mausitem ist ein Panel, dessen Hintergrundbild ja ein bmap-Pointer sein sollte, das müsste ja in meinem Code stimmen.
Skill 99 wird bisher nicht benutzt/überschrieben.

Hättest du noch eine Idee, wo eine Fehlerquelle sein könnte?

edit: ein
Code:
fallengelassener_gegenstand->ent_entity->tilt += 3;

im Event hat die selbige Fehlermeldung produziert, also irgendwie muss an der Zuweisung
Code:
gegenstand* fallengelassener_gegenstand = (gegenstand*)my->skill[99];

falsch laufen, ich weis nur noch nicht, was
Posted By: TechMuc

Re: [solved] struct-Name per Laufzeit erstellen - 09/19/11 03:46

Überprüfe ich morgen mal - das was ich da geschrieben habe ist eig. standard c verhalten - kann sein, dass litec was anderes will.

Gruß,
Timo
Posted By: JoGa

Re: [solved] struct-Name per Laufzeit erstellen - 09/20/11 18:29

OH, MEIN GOTT!
ES KLAPPT :-D

und zwar habe ich nun bei
Code:
fallengelassener_gegenstand->ent_entity.skill[99] = (int)(void*)fallengelassener_gegenstand;



Code:
fallengelassener_gegenstand->ent_entity.skill[99] = (int*)fallengelassener_gegenstand;


den Pointer-* bei der int gesetzt und das void gelöscht, nun klappt es :-)

VIIIIEEEELEN Dank (vorerst crazy) für deine Eselsgeduld und Erklärungen!
Ich werd dann mal mit den Gegenständen so weitermachen und schaun, wie weit ich komme :-)
Posted By: TechMuc

Re: [solved] struct-Name per Laufzeit erstellen - 09/20/11 19:43

Hmm klar.. da siehst du genau was ich gemeint habe.. Wenn du zu (int) konvertierst, dann versucht der Compiler die (int) dem (var) - also dem Skill - zuzuweisen. Der Compiler kennt eine Konvertierungsregel zwischen int und var (left shift by 10) und zerstört deinen schönen Pointer.

Wenn du zu (int*) castest, kennt der Compiler keine Regel und lässt deinen Pointer in ruh.
Posted By: JoGa

Re: [solved] struct-Name per Laufzeit erstellen - 09/22/11 15:01

noch eine kleine prinzipielle Frage hab ich:

Prinzipiell sollten genauso viele free()-Befehle wie malloc()-Befehle aufgerufen werden, um keinen "Memory Leak" zu produzieren - richtig?

...ist ja eigentlich logisch, aber sicherheitshalber frag ich mal nach, um Gewissheit zu bekommen :-/
Posted By: TechMuc

Re: [solved] struct-Name per Laufzeit erstellen - 09/22/11 20:04

richtig
Posted By: WretchedSid

Re: [solved] struct-Name per Laufzeit erstellen - 09/22/11 21:17

Halb richtig. Wenn du dein Programm beendest ist es günstiger einfach den Speicher zu "leaken" anstatt für jeden blöden block Speicher free() aufzurufen. Windows wird automatisch und deutlich effizienter den ganzen belegten Speicher auf einmal wegräumen.
Posted By: FlorianP

Re: [solved] struct-Name per Laufzeit erstellen - 09/23/11 04:18

Sry aber das ist ein ganz schlechter Rat.
Allozierten Speicher offen liegenzulassen ist bestenfalls grob fahrlässig und führt zu absolut unwartbarem code! Ein kleiner Denkfehler oder eine kleine unbedachte Änderung im Programm und du erzeugst fröhlich durch die Gegend leakenden code.
Bei 1-Mann Hobbyprojekten kann man das ganz vorsichtig vielleicht mal machen aber im Zweifel bringt dir die gesparte Sekunde fürs 'free' schreiben später mehrere Stunden Fehlersuche ein.

An der Stelle kann ich also nur wieder zitieren:

Originally Posted By: C++ Coding Standard CERN-UCO/1999/207
Optimise code only when you know you have a performance problem.
This means that during the implementation phase you should write code that is easy to read,
understand and maintain. Do not write cryptic code, just to improve its performance.
Performance problems are more likely solved at an architecture and design level.

Posted By: JoGa

Re: [solved] struct-Name per Laufzeit erstellen - 09/23/11 08:32

okay, vielen Dank euch dreien.
Dh. ich programmier mein Inventar erstmal, sodass es bezüglich Funktion und Bugs läuft, und werd dann beim Code "ins Reine schreiben"/optimieren mir die Speicherblöcke zur Brust nehmen.
Posted By: WretchedSid

Re: [solved] struct-Name per Laufzeit erstellen - 09/23/11 10:42

Florian, wenn du bitte noch einmal lesen würdest was ich geschrieben habe, wüsstest du das es nicht um die Zeit die es braucht um free() zu schrieben sondern die Zeit die es braucht ~500 mal free() aufzurufen um am ENDE des Lebenszyklus des eigenen Programmes noch "schnell" den Speicher zu freen der sowieso danach deutlich schneller vom OS gefreed werden könnte.
Posted By: FlorianP

Re: [solved] struct-Name per Laufzeit erstellen - 09/23/11 15:38

Das Programmende kann sicherlich dem free zuvorkommen aber darf es nie völlig ersetzen.
Wenn ich dich falsch verstanden hab okay - wollts aber dem Threadersteller zuliebe nochmal erwähnt haben.
© 2024 lite-C Forums