Ich habe mich für die D-Sprache interessiert und fing an, sie zu lernen, weil ich der Meinung bin, dass sie einfacheres und effizienteres Codieren als C oder C++ unterstützt, während sie den Code in diesen anderen Sprachen verwendet.Wie erstellt man kontinuierliche mehrdimensionale Arrays in D, die mit C-Code verbunden werden können?
jedoch versucht, eine 2D-Array zu konstruieren ich das beobachtet:
auto a = new double[][](1000,3); // clean and seemingly elegant
a.length = 0; // To fill the array by ~= operator
a ~= [1, 2, 3]; // fill the first row
writeln(a); // -> [[1, 2, 3]] (OK)
writeln(a.capacity,a[0].capacity); // -> 1 3 (should be 1000 3)
Es schon falsch anfühlt, als ich den Wunsch explizit ausgedrückt Speicher für 1000x3 Zahlen zu reservieren. Sowohl Digital Mars D als auch GCC gdc Compiler erzeugen jedoch das gleiche Ergebnis.
Um das Array wirklich zweidimensional zu machen, habe ich eine weitere Zeile hinzugefügt. einen festen Block des Speichers mit der Größe des 3*3*double.sizeof
und zeilenweise besetzten Layout
a ~= [3, 4, 5]; // add another row
writeln(a); // -> [[1, 2, 3], [4, 5, 6]] (OK)
writeln(a.capacity,a[0].capacity); // -> 3 3
akzeptabel Dies könnte, wenn es, dass der Inhalt a
gemeint. Aber mehr Überraschungen auf dem Weg - wenn ich das Layout dieser Anordnung aus der C-Sicht überprüfen will:
double* p = &(a[0][0]); // get a C-like pointer to the data
for(size_t i=0; i<20; i++) {
writef("%.0f ", *(p+i)); // should be: 1 2 3 4 5 6 nan nan ...
}
writeln();
Ich habe verwirrende Ergebnisse und verschiedene unter Compiler. DMD mit libphobos2 (Version 2.071.0) sagte:
1 2 3 0 0 0 0 0 4 5 6 0 0 0 0 0 0 0 0 0
aber mit GDC (GCC Version 4.8.4) der gleiche Code dies gedruckt:
1 2 3 0 nan nan nan 0 nan nan nan 0 nan nan nan 0 nan nan nan 0
Ups. Dies ist weder verwendbar noch tragbar. Entweder ist das Array überhaupt nicht kontinuierlich (daher lese ich einen anderen Speicher), oder beide Implementierungen sind fehlerhaft, weil die Initialisierung mit nan
garantiert sein sollte. OK, ich weiß schon, dass ich malloc
verwenden kann und alles so machen kann, wie ich es in C machen würde, aber dann sehe ich nicht den Vorteil, ein anderes riesiges Biest eine Sprache mit eigenen schrulligen Hacks zu lernen.
Gibt es eine saubere Möglichkeit, kontinuierliche mehrdimensionale Arrays mit C-Layout zu erstellen, ohne die Vorteile von D wie Speicherverwaltung, Bereiche, Slices, Algorithmen usw. zu verlieren?
Edit:
Nach der Antwort von @weltensturm ich meine Fehler behoben und ich habe ein wenig mehr Tests. Ich brauche tatsächlich ein dynamisches Array, weil ich die Zahlen aus FIFO lese und ich weiß nicht a priori, wie viele Zeilen zu erwarten sind. Dieser Code offenbar funktioniert:
auto as = new double[3][0]; // Inconsistent w/C: this is 0 rows by 3 columns
auto ad = new double[][](0,3); // also 0 x 3
as ~= [1,2,3]; as ~= [4,5,6];
ad ~= [1,2,3]; ad ~= [4,5,6]; // I can append to both
writeln(as); // -> [[1, 2, 3], [4, 5, 6]]
writeln(ad); // -> [[1, 2, 3], [4, 5, 6]]
writefln("as capacity: %dx%d", as.capacity, as[0].capacity);
// -> as capacity: 2x0
writefln("ad capacity: %dx%d", ad.capacity, ad[0].capacity);
// -> ad capacity: 3x3
double* p = &(as[0][0]);
for(size_t i=0; i<6; i++) writef("%.0f ", *(p+i)); // -> 1 2 3 4 5 6
writeln();
p = &(ad[0][0]);
for(size_t i=0; i<9; i++) writef("%.0f ", *(p+i)); // -> 1 2 3 4 5 6 0 0 0
writeln();
Sowohl as
und ad
sind tatsächlich dynamisch und werden auf Anfügen der Größe verändert, aber sie verhalten sich anders - Blick auf die Kapazitäten nach den anhängt.
Nun ist die Frage, kann ich auf das Verhalten einer dieser Alternativen verlassen? Ist die Sprache mindestens für die new double[3][0]
Syntax garantiert? Ist es möglich, das Layout und die Kontinuität für das "dynamische" Array (new double[][](0,3)
) zu garantieren, vorausgesetzt, ich weiß, was nicht zu tun (z. B. nicht die Eigenschaft length
direkt ändern)?
Sie haben ein dynamisches Array von dynamischen Arrays. Sie benötigen einen kontinuierlichen Speicherbedarf, um die innere Dimension statisch zu halten. –