Daten aus einem struct kopieren, gibts da nen Trick?
-
OkkaPapa schrieb:
Sind eben viele for-Schleifen und beim testen sind die Datensätze ja eher klein...
Daher die Frage, ob es evt. schneller geht.
Am struct darf ich nicht mehr viel rumfummeln und an Statistics eher gar nicht!Ich verstehe.
Aber Du wirst ja wahrscheinlich eher selten einen Messpunkt wieder verändern. Eher einen Haufen Messpunkte speichern und danach da durchpflügen wollen...Deswegen nochmal schematisch mein Ansatz, der aus Deinem "Array of Struct" ein "Struct of Arrays" macht.
typedef struct{ // wie gehabt } Type_Measured; struct series{ int *type; int *usercode; char *label[LABELLEN]; double *value1; double *value2; int len; // Anzahl d. Eintraege }; struct series* get_series(){ /* Konstruktor */ } void free_series(struct series* s){ /* destruktor */ } void push_back(const Type_Measured* m, struct series* s){ /* auseinanderpfluecken & anfuegen */ } // wenn Du wirklich einen einzelnen Punkt brauchst... Type_Measured get(int i, const struct series *s){ assert(i<s->len); Type_Measured result = {s->type[i], s->usercode[i], {0}, ///... }; memcpy(result.Label, s->label[i], LABELLEN); return result; } int stat1(const struct series *s){ return Statistic(/*....*/, s->values1, s->len); /* Baa-am! */ }
-
Goddamn it!
Die Deklaration vonseries.label
ist falsch...
-
Kann das bitte jmd. etwas genauer erklären, was hier passiert?
typedef struct{double x[6];} Copyst; ... Type_Measured t; double a[6]; *(Copyst*)a=*(Copyst*)&t.Value1;
-
unsure110 schrieb:
Kann das bitte jmd. etwas genauer erklären, was hier passiert?
Sehr schmutzige Dinge!
-
unsure110 schrieb:
Kann das bitte jmd. etwas genauer erklären, was hier passiert?
typedef struct{double x[6];} Copyst; ... Type_Measured t; double a[6]; *(Copyst*)a=*(Copyst*)&t.Value1;
Kannst du genauer erklären, was du da dran nicht verstehst?
Das einzige, was da "passiert", ist das Gleichheitszeichen, also eine Zuweisung. Von t.Value1 auf a. Der Rest ist Syntaxgeschwurbel, damit der Compiler diese Sprachvergewaltigung ohne Murren akzeptiert.
-
... und anstatt zu erklären, was da passiert, wird nur gesagt, dass es schlecht ist ...
Also gut, ich versuch's mal:
a[6]
wird nicht gepadded. Die Elemente von Arrays werden grundsätzlich nicht gepadded. C99 verbietet das sogar. Der Grund dafür ist, dass wenn du die Elemente eines Arrays indizierst, im Grunde immer nur der Index * sizeof(Typ des Arrays) + Speicheradresse des ersten Arrayelementes gerechnet wird. Der Zugriff muss halt einheitlich erfolgen.Also hast du 6 * sizeof(double) (meistens
Bytes == 48 Bytes insgesamt, in die du schreiben kannst. Die Werte in dem Struct sind aber keine Arrays, sondern einzelne Werte - heißt, der Compiler darf und kann da Padding einfügen. Das Struct ist dann 6 * 8 Bytes + <Padding> == 48 + <Padding>. Und das "+ <Padding>" kann dir dann so richtig schön auf die Füße fallen. Und Programme willst du in der Regel so deterministisch wie möglich ablaufen lassen, weil sonst das Debugging einen Heidenspaß macht (nur nicht für dich).
Also ein wenig deutlicher:
struct a{char x[48];} a1; struct b{char x[48+padding];} b1; /*padding kann 0 sein, oder auch nicht.*/ a1=*(struct a*)&b1; /*Kann Überlauf verursachen oder auch nicht.*/
Kurz: Lass es.
-
Insgesamt ist es aber eine ziemlich gute Wette, dass ein Compiler kein Padding zwischen den Membern eines structs der Form
struct { Foo foo1, foo2, foo3, /* ... */ fooN; };
einführen wird. Egal wie abgefahren Foo ist. Und erst recht nicht, wenn es primitive Datentypen sind. Auch wenn dieses Verhalten streng genommen aus den Regeln der Sprache so nicht hervor geht.
-
Übrigens habe ich oben ein wenig scheiße erzählt - hätte mir auch vorher klar sein können:
#include <stdio.h> #include <stdint.h> struct a{char x[48];} a1; struct b{char x[56];} b1; int main(void) { size_t i; /*Speicher befuellen.*/ for(i=0;i<56;i++) b1.x[i]=i; /*Zuweisung.*/ a1=*(struct a*)&b1; /*WARNUNG: kann undefiniertes Verhalten hervorrufen. In der Regel ist **zwar genug Platz im globalen Datensegment, aber man weiss ja nie ... ***/ for(i=48;i<56;i++) printf("%i|",a1.x[i]); puts(""); return 0; }
Ausgabe:
0|0|0|0|0|0|0|0|
Heisst, der Compiler passt schon auf, dass es nicht zu einem Überlauf kommt. Sonst wäre an dieser Stelle die Zahlen 48 bis 55 erschienen. Aber das Problem, dass du plötzlich undefinierte Werte in deinem Array haben kannst, besteht natürlich immer noch.
-
Was soll da dran ungewöhnlich oder überraschend sein? Du kopierst ein struct a, natürlich wird da nur so viel kopiert, wie ein struct a groß ist.
-
Ja, das ist mir jetzt auch klar.
Hatte aber vorher die wirre Idee, dass durch den Zeiger-cast kein temporäres Objekt erstellt wird, sondern die Werte 1:1 geschrieben werden.