[C++] Array unbekannter Größe statisch initialisieren

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Antworten
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

[C++] Array unbekannter Größe statisch initialisieren

Beitrag von Krishty »

Hi,

Ich habe ein Array Type const array[], das static const initialisiert werden soll. Das steckt aber in einer struct. In einer Klasse darf man keine Arrays unbekannter Größe benutzen. Logisch. Also in einen Zeiger umwandeln:

struct Data { Type const * ptr; };

Wie kriege ich das jetzt initialisiert?

static Data const foo = { { { 1 }, { 2 }, { 3 } } }; // error: cannot convert from 'int' to 'Type const *'
(Die Klammern habe ich ja auch nur zum Spaß da hingeschrieben, du dumme Syntaxamöbe eines Compilers)

Unter C99 würde ich ja schreiben:

static Data const foo = { .ptr = { { 1 }, { 2 }, { 3 } } }
Aber das geht ja im tollen C++ nicht -.-

Gibt es da wirklich keine andere Möglichkeit als eine Zwischenvariable?

static Type const fooArray[] = { { 1 }, { 2 }, { 3 } };
static Data const foo = { fooArray };


Gruß, Ky
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Sternmull
Establishment
Beiträge: 264
Registriert: 27.04.2007, 00:30
Echter Name: Til
Wohnort: Dresden

Re: [C++] Array unbekannter Größe statisch initialisieren

Beitrag von Sternmull »

Du könntest das Array als String Literal schreiben und dessen Adresse in den Zieltyp casten :)

Aber im Ernst: Auch wenn Deine Lösung nicht so schön ist wie sie sein sollte... es lässt sich doch damit leben.
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [C++] Array unbekannter Größe statisch initialisieren

Beitrag von Krishty »

Ja, für eine einzelne Instanz. Leider muss ich tausend dieser Instanzen in einem Array initialisieren. Tausend Zwischenvariablen zu deklarieren, jede einzeln einzutragen und dieses Monster auch noch zu warten ist …

… okay; ich merke mitten in dem Satz, das das voll und ganz nach etwas klingt, was ich tun würde. Aber nur, wenn es echt nicht anders geht.

Das mit dem String-Literal habe ich mir auch schon überlegt – aber da das Daten-Layout noch nicht final ist, würde jede Änderung an der Datenstruktur (man bedenke u.a. auch Padding des Compilers!) den String unbrauchbar werden lassen. Es ist zum heulen.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Sternmull
Establishment
Beiträge: 264
Registriert: 27.04.2007, 00:30
Echter Name: Til
Wohnort: Dresden

Re: [C++] Array unbekannter Größe statisch initialisieren

Beitrag von Sternmull »

Ist der ganze Ansatz denn wirklich notwendig? Was spricht dagegeben die Daten in eine Datei zu schreiben und dann dort raus zu lesen?
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [C++] Array unbekannter Größe statisch initialisieren

Beitrag von Krishty »

Dass das noch langsamer wäre als sie erst zu initialisieren.

Mir wurde gerade ein interessanter Vorschlag gemacht: Ein Element pro Zeile initialisieren, dabei die erste und letzte Zeilennummer per Makro speichern und in ein static_assert() packen. Mal gucken, ob ich das hinkriege.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Chromanoid
Moderator
Beiträge: 4254
Registriert: 16.10.2002, 19:39
Echter Name: Christian Kulenkampff
Wohnort: Lüneburg

Re: [C++] Array unbekannter Größe statisch initialisieren

Beitrag von Chromanoid »

Schon mal über einen Code Generator, der aus Dateien in einem precompile step entsprechenden Code generiert, nachgedacht?
Benutzeravatar
Sternmull
Establishment
Beiträge: 264
Registriert: 27.04.2007, 00:30
Echter Name: Til
Wohnort: Dresden

Re: [C++] Array unbekannter Größe statisch initialisieren

Beitrag von Sternmull »

Warum muss das langsamer sein? Wenn man die Daten per Memory Mapped file einliest, und die da drin schon das richtige Layout haben, dann dürfte es doch die gleiche Performance haben als würde man sie aus dem Binary lesen.
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [C++] Array unbekannter Größe statisch initialisieren

Beitrag von Krishty »

Man muss die Datei aber erst öffnen, und das bedeutet: Ab in den Kernel, den die Datei suchen lassen, Rechte prüfen, währenddessen auf die HDD warten, HANDLE reservieren, zurück zur Anwendung. Dann wieder ab in den Kernel, irgendwas machen, was eigentlich nur Anwendungen brauchen, die häppchenweise mappen wollen (nämlich CreateFileMapping()), HANDLE reservieren, zurück zur Anwendung. Dann wieder Kernel, Seite suchen, Seite reservieren, zurück zur Anwendung. Und beim ersten Zugriff dann: Seitenfehler, Kernel, auf die HDD warten, weitermachen. Und eine Indirektion mehr, weil ich jetzt zu einer unbekannten Adresse springen muss.

Dazu dann meinerseits Quelltext, um zu verarbeiten, falls die Datei nicht existiert oder fehlerhaft ist.

Ganz genau dafür ist das Datensegment der Exe da. Die Exe wird ja sowieso gemappt und eingelesen, da kann man sich den ganzen Scheiß auch sparen und liest einfach ein paar KiB mehr.

Nicht zuletzt: Ich schreibe in meinem Projekt nicht bloß Integer, sondern Datenstrukturen. Ich bräuchte also erstmal einen Parser, der mir die menschenlesbaren Initialisierungsdaten in eine binäre Datei umwandelt, wenn ich was an der Datenstruktur ändere (nobody's perfect). Davon habe ich auch schon zu viele. Und genau für sowas sollte eigentlich der Compiler da sein: Array definieren, enums/floats/ints/Strings reinschreiben, wie man lustig ist, fertig.

Wenn diese Dreckssprache nicht einfach mit Nullen auffüllen würde, statt einen Fehler zu melden. Das ist doch wirklich so archetypisch. Irgendeine vollkommen ahnungslose Amöbe meinte 1978, dass es toll wäre, wenn sie zwei Nullen weniger im Quelltext schreiben dürfte und dafür muss ich jetzt leiden.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Sternmull
Establishment
Beiträge: 264
Registriert: 27.04.2007, 00:30
Echter Name: Til
Wohnort: Dresden

Re: [C++] Array unbekannter Größe statisch initialisieren

Beitrag von Sternmull »

Was bitteschön machst du denn? Pro Frame dein Programm neu starten?

Die Komplexität der Datenstrukturen würde doch gerade dafür sprechen sie in einem einfach wartbaren Format zu entwickeln und dann während des Build-Prozesses in etwas effizient ladbares umzuwandeln. Tausende von Arrays sind doch auch nicht der Hit. Es gibt mit Sicherheit auch die Möglichkeit der Exe im Nachhinein noch Datein einzuimpfen und vielleicht auch gleich einen Pointer darauf zu setzen. Aber ich würde diese Mühe scheuen und einfach aus einer zweiten Datei lesen. Ich würde mich auch nicht drauf verlassen das der Kernel das Binary nicht auch bloß ähnlich einem Memory Mapped File öffnet und die Seiten bei Bedarf nachlädt.
Benutzeravatar
Sternmull
Establishment
Beiträge: 264
Registriert: 27.04.2007, 00:30
Echter Name: Til
Wohnort: Dresden

Re: [C++] Array unbekannter Größe statisch initialisieren

Beitrag von Sternmull »

Grad fällt mir ein das du die Daten auch während des Builds zu Quellcode formatieren könntest der sie als Array enthält. Das könnte genau so gut im Build untergebraucht werden wie die Kovertierung zu einer Binärdatei, mit dem Unterschied das man halt jedes mal die generierte Datei kompilieren und das Binary linken muss wenn sich was an den Daten geändert hat. Das wird ja z.B. gemacht um Bild-Daten einzubetten.

Edit: Oops, auch ich hatte den Beitrag von Chromanoid überlesen... da Stand genau der Vorschlag drin.
Zuletzt geändert von Sternmull am 20.04.2011, 22:29, insgesamt 1-mal geändert.
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [C++] Array unbekannter Größe statisch initialisieren

Beitrag von Krishty »

Chromanoid hat geschrieben:Schon mal über einen Code Generator, der aus Dateien in einem precompile step entsprechenden Code generiert, nachgedacht?
Ups, den Post hatte ich ganz übersehen, sry. Ja; ich bin eben darauf gestoßen, dass ich die Erzeugung all der Variablen per Präprozessor automatisieren könnte. Ich checke gerade, inwiefern das machbar ist.
Sternmull hat geschrieben:Die Komplexität der Datenstrukturen würde doch gerade dafür sprechen sie in einem einfach wartbaren Format zu entwickeln und dann während des Build-Prozesses in etwas effizient ladbares umzuwandeln.
Und genau das ist es, wenn ich schreibe: array = { { 133, 't', "C++ ist scheiße und " }, { 0, 'x', " kommt nie an" }, … }; und mir der Compiler das dann in was reinbackt, wo es mir scheißegal sein kann, wo es landet und wie die Struktur im Detail aussieht und einfach nur array[x].y; schreiben muss.
Sternmull hat geschrieben:Ich würde mich auch nicht drauf verlassen das der Kernel das Binary nicht auch bloß ähnlich einem Memory Mapped File öffnet und die Seiten bei Bedarf nachlädt.
Doch. Und selbst, falls nicht, würde das oben immernoch zu einem lächerlichen Seitenfehler statt zu drei OS-Aufrufen kollabieren.

Diese Scheißsprache will es einfach nicht zulassen, dass ich die banalsten Dinge halbwegs ohne Nervenzusammenbruch artikulieren kann. Da kriege ich so den Hass. In C++0x würde es ja per C99-Initialisierer gehen, aber um das zu unterstützen ist sich mein Lieblings-Compiler ja zu schade.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Chromanoid
Moderator
Beiträge: 4254
Registriert: 16.10.2002, 19:39
Echter Name: Christian Kulenkampff
Wohnort: Lüneburg

Re: [C++] Array unbekannter Größe statisch initialisieren

Beitrag von Chromanoid »

Evt. in einem XML Format und die Übersetzung in Quellcode übernimmt dann ein XSLT - ich glaube das geht. Und wenn du was an der Klasse ändern willst, dann jagst du über die alte XML Datei einfach ein "Refactoring XSLT" drüber...

edit: ah mit XSL:FO und zum Beispiel http://xmlgraphics.apache.org/fop ginge textausgabe. Und bei einem Refactoring nimmst du dann einen XSLT... geht auch so mit xslt...
XSL

Code: Alles auswählen

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="text"/>	
<xsl:template match="/">
<xsl:for-each select="catalog/cd">
	<xsl:value-of select="title"/>
	<xsl:value-of select="artist"/><xsl:text>
</xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Eingabe:

Code: Alles auswählen

<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="cdcatalog.xsl"?>
<catalog>
	<cd>
		<title>Empire Burlesque</title>
		<artist>Bob Dylan</artist>
		<country>USA</country>
		<company>Columbia</company>
		<price>10.90</price>
		<year>1985</year>
	</cd>
	<cd>
		<title>Hide your heart</title>
		<artist>Bonnie Tyler</artist>
		<country>UK</country>
		<company>CBS Records</company>
		<price>9.90</price>
		<year>1988</year>
	</cd>
</catalog>
Ausgabe:
Empire BurlesqueBob Dylan
Hide your heartBonnie Tyler
Dirk Schulz
Establishment
Beiträge: 130
Registriert: 01.03.2009, 14:21
Alter Benutzername: frittentuete

Re: [C++] Array unbekannter Größe statisch initialisieren

Beitrag von Dirk Schulz »

Hi,

vielleicht habe ich einen wichtigen Schritt übersehen, aber für meine Direct3d-Vertexdeklarationen benutze ich das andauernd. :?:

Hier mal ein Auszug:

ParticleVertex.h:

Code: Alles auswählen

typedef struct
{
        ...

	static const D3DVERTEXELEMENT9 vert_element[];

} ParticleVertex;
ParticleVertex.cpp:

Code: Alles auswählen

#include "ParticleVertex.h"

const D3DVERTEXELEMENT9 ParticleVertex::vert_element[] = {

	{ 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
	{ 0, 12, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_PSIZE, 0 },
	{ 0, 16, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
	{ 0, 24, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
	{ 0, 28, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0 },
	D3DDECL_END()
	
};
Das funktioniert. Allerdings weiß ich nicht, ob bei dir noch andere Sachen mit hineinspielen, die das verhindern könnten. :!:
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [C++] Array unbekannter Größe statisch initialisieren

Beitrag von Krishty »

Dirk Schulz hat geschrieben:Allerdings weiß ich nicht, ob bei dir noch andere Sachen mit hineinspielen, die das verhindern könnten. :!:
Dass es bei mir in einer struct liegt – das hier geht z.B. nicht:

Code: Alles auswählen

struct VDecl {
    // D3DVERTEXELEMENT9 vert_element[]; // Fehler: Arrays unbekannter Größe dürfen keine Attribute sein. Darum:
    D3DVERTEXELEMENT9 const * vert_element;
};

static VDecl const foo = {
    {
        { 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, // Fehler bei der zweiten Null: Zu viele Initialisierer (der Compiler ignoriert die zweiten geschweiften Klammern und interpretiert die erste 0 nicht als Wert für das Vertex-Element, sondern für VDecl::vert_element)
        …
        D3DDECL_END()   
    }
};

// Mit C99/C++0x dürfte es gehen:
static VDecl const foo = {
    .vert_element = {
        { 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
        …
        D3DDECL_END()   
    }
};
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Dirk Schulz
Establishment
Beiträge: 130
Registriert: 01.03.2009, 14:21
Alter Benutzername: frittentuete

Re: [C++] Array unbekannter Größe statisch initialisieren

Beitrag von Dirk Schulz »

Hi,

jetzt habe ich meinen Denkfehler verstanden. Das Array kann von Instanz zu Instanz verschieden sein.

Wie siehts denn mit c++0x und Variadic templates aus?

Wäre vielleicht eine Alternative, habe mich damit aber noch nicht befasst, deswegen weiß ich nicht, ob intern nicht auch Zwischenvariablen benutzt werden.
Helmut
Establishment
Beiträge: 237
Registriert: 11.07.2002, 15:49
Wohnort: Bonn
Kontaktdaten:

Re: [C++] Array unbekannter Größe statisch initialisieren

Beitrag von Helmut »

Wie wär's wenn du eine maximale Größe des Arrays festlegst und die nicht benötigten Elemente selber nullst?
Ist natürlich u.U. etwas verschwenderisch, aber einfach.
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [C++] Array unbekannter Größe statisch initialisieren

Beitrag von Krishty »

Dirk Schulz hat geschrieben:Wie siehts denn mit c++0x und Variadic templates aus?
Wenn mir C++0x uir Verfüging stünde, kömnte ich auch gleich die C99.Syntax benutzen
Helmut hat geschrieben:Wie wär's wenn du eine maximale Größe des Arrays festlegst und die nicht benötigten Elemente selber nullst?
Ist natürlich u.U. etwas verschwenderisch, aber einfach.
Ja, habe ich auchj schon dürber nachgedacht
Aber bei 1000 Array-Elemenenbten, die imSchnitt eine Größe von 3 und maxima eine Größe von 10 haben wären >50 % verschwendet
Bääääh
Ihc glaube, ich mache das jezt mit #defines
Das ist der einzgie Grund, wofür man dne bekackten Präprozessor noch benutzen kann
Umd die schwächen der Sprache auszugleichen
Hass
Ehrlich, ich habe die Schnauze sowas von gehstrichen voll von der ganzen Scheiße (nicht nmur C++ sondern generell)
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Aramis
Moderator
Beiträge: 1458
Registriert: 25.02.2009, 19:50
Echter Name: Alexander Gessler
Wohnort: 2016
Kontaktdaten:

Re: [C++] Array unbekannter Größe statisch initialisieren

Beitrag von Aramis »

Haettest du halt vorher nicht jedes Byte an Platz muehsam rausgepfriemelt - dann wuerden dir die paar verschwendeten Bytes jetzt nicht das Herz brechen :-)
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [C++] Array unbekannter Größe statisch initialisieren

Beitrag von Krishty »

Wäre ich halt statt mühsam zu programmieren dabei geblieben, mich über anderer Leute Prinzipien lustig zu machen
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Antworten