Typumwandlung mit Union fehlerhaft?
-
Hallöchen.
Heute ist nicht mein Glückstag. Nachdem ich das letzte Problem gelöst habe, geht es gleich mit dem nächsten weiter.
Ich habe ein Union definiert um ein Hex-Wert (2 Byte) aus einer Datei zu lesen und als (Short-)Int weiter zu verarbeiten.
union union_def { double d; unsigned short i[4]; unsigned long ul[2]; long l[2]; unsigned char c[8]; };
Weiterbenutzt wird das folgendemaßen:
union union_def union_rechnen; for(m=0;m<2;m++){ union_rechnen.c[m]=fgetc(FDatei); } data = ccparam[k][union_rechnen.i[0]];
Die Matrix sieht folgendermaßen aus ccparam[5][32].
Mit printf ausgegeben weiß ich, dass die zwei eingelesenen Chars 8 und 1 heißen. Ergibt 18(hex) = 24. Soweit bestens. Gebe ich mir allerdings den Short-Int auch mit printf aus, erzählt der mir etwas von 264. 264 passt nun aber nicht in meine Matrix.
Meine Vermutung: 264 = 108(hex). Also statt 8 und 1 ließt er 08 und 01.
sizeof bestätigt mir aber Char=1, Short-Int=2.
Ich verstehe es nicht. Irgendwelche Ideen?
Danke schonmal.
Grüße,
Blue][ce
-
evtl. ists aus dem Kontext gerissen aber du schreibst Member Array c
"union_rechnen.c[m]"
und liest Member Array i das wahrscheinlich noch mit random Data gefüllt ist
"union_rechnen.i[0]"union union_def union_rechnen; for(m=0;m<2;m++){ union_rechnen.c[m]=fgetc(FDatei); } data = ccparam[k][union_rechnen.i[0]];
natürlich müssen die "ascii" hex chars auch in ein int konvertiert werden
-
Blue][ce schrieb:
Mit printf ausgegeben weiß ich, dass die zwei eingelesenen Chars 8 und 1 heißen. Ergibt 18(hex) = 24. Soweit bestens.
Nein, soweit Mumpitz. Ein char ist ein Byte, und ein Byte repräsentiert zwei Hex-Ziffern, nicht eine. 264 klingt schon ganz richtig.
Scheint, als ob deine Zeichen ASCII-codiert sind, dann geht das so ohnehin nicht.
-
c_newbie schrieb:
evtl. ists aus dem Kontext gerissen aber du schreibst Member Array c
"union_rechnen.c[m]"
und liest Member Array i das wahrscheinlich noch mit random Data gefüllt ist
"union_rechnen.i[0]"Das kann ich mir nicht vorstellen. Da müßte ich die Funktion eines Union ja komplett falsch verstanden haben. Ich schreibe doch genau deshalb die Werte in den selben Speicherbereich um da mein Int rausfischen zu können.
MFK schrieb:
Nein, soweit Mumpitz. Ein char ist ein Byte, und ein Byte repräsentiert zwei Hex-Ziffern, nicht eine. 264 klingt schon ganz richtig.
Ich hab langsam das Gefühl ich blamier mich hier.
Du hast natürlich Recht. Ich geh meinen Quelltext und meine Datenfile nochmal durch. Vielleicht ist 264 doch plausibel und mein Array ist mit Größe 32 einfach fehldimensioniert. Oder ich positioniere meinen Lese-Zeiger falsch ... aber bei einer Zahl für die 2 Byte Speicher veranschlagt sind, wäre es schon albern wenn die größte Zahl 32 sein soll und das zweite Byte ungenutzt bleibt.
Ich meld mich wieder. Danke!
-
hab mir das grad nochmal angeschaut, und so ungern ich das sag, du hast recht.
dachte ein union ist wie ein struct aber da lag ich falsch. sry falls ich
damit verwirrung gestiftet hab.
-
Hoi.
c_newbie schrieb:
hab mir das grad nochmal angeschaut, und so ungern ich das sag, du hast recht.
dachte ein union ist wie ein struct aber da lag ich falsch. sry falls ich
damit verwirrung gestiftet hab.Kein Problem. Ich freue mich über jeden Hilfeversuch. Ist ja schon schwer genug bei solchen Programmauszügen überhaupt zu verstehen, was der Coder damit bezwecken wollte.
Bin dem Problem gerade auf der Spur. Zum einen ist mein Lese-Zeiger tatsächlich minimal falsch (und das ist mir seit Wochen nicht aufgefallen), zum anderen habe ich schlicht die falsche Variable verwendet.
Mein "union_rechnen.i[0]
" enthält nicht die Zelle für den Wert, sondern den Wert selbst ... hab da irgendwas verdeht, bin aber noch nicht komplett dahinter gestiegen.
Manche Codestellen sind Monate alt und meine Dokumentation ist, entgegen besseren Wissens, dürftig.Grüße,
Blue][ce
-
vllt. kann ich damit bischen helfen?
#include <stdio.h> #include <stdlib.h> int main(void){ union union_def { double d; unsigned short i[4]; unsigned long ul[2]; long l[2]; unsigned char c[8]; }; union union_def ur; ur.i[0] = 264; ur.c[0] = ur.c[0]|(ur.c[1]<<4); ur.c[1] = 0;//@added }
@added
muß natürlich dann resetted werden dass der wert in .i[0] stimmt.
-
Blue][ce schrieb:
Da müßte ich die Funktion eines Union ja komplett falsch verstanden haben. Ich schreibe doch genau deshalb die Werte in den selben Speicherbereich um da mein Int rausfischen zu können.
aber da ist der haken. alle union-members teilen sich zwar den speicher, aber es immer nur der gültig, der zuletzt beschrieben wurde. du solltest unions nicht zum typkonvertieren missbrauchen, wenn's geht, ist es reine glückssache. nimm die beiden bytes, shift und odere sie zusammen. das geht immr.
-
@c_newbie: Das isses nicht. Das Union funktioniert einwandfrei. Man muß einfach nur wissen was man tut. ^^
Hab den Fehler gefunden. War tatsächlich ein Denkfehler meinerseits.
Mehrdimensionale Matrizen sind einfach verwirrend.Danke für eure Hilfe.
Wir hören bestimmt demnächst nochmal von einander.Grüße,
Blue][ce
-
\fricky schrieb:
aber da ist der haken. alle union-members teilen sich zwar den speicher, aber es immer nur der gültig, der zuletzt beschrieben wurde. du solltest unions nicht zum typkonvertieren missbrauchen, wenn's geht, ist es reine glückssache. nimm die beiden bytes, shift und odere sie zusammen. das geht immr.
Ich lese ja nur aus, wenn ich auch was hineingeschrieben habe.
Mein Betreuer (das ganze hier ist ne Diplomarbeit) hat mich extra den Code umstellen lassen um die Unions zur Typkonvertierung zu nutzen. Er begründet das mit Rechenzeitvorteilen. Unbearbeitet lesen geht einfach schneller als die Werte vorher zu bearbeiten.
Die Software soll eben mit mehreren GByte an Daten umgehen können. Da summiert sich auch so ein kleiner Zeitunterschied.Grüße,
Blue][ce
-
Evtl. würds dann auch Sinn machen den String in größeren Chunks einzulesen und
dann aufzuteilen(bearbeiten) statt jedes Char einzeln abzuholen.Den Loop könnte
man aus Preformance gründen auch unrollen allerdings müßte man das eh etwas
anders angehen wenn man größere chunks holt.
-
c_newbie schrieb:
Evtl. würds dann auch Sinn machen den String in größeren Chunks einzulesen und
dann aufzuteilen(bearbeiten) statt jedes Char einzeln abzuholen.Den Loop könnte
man aus Preformance gründen auch unrollen allerdings müßte man das eh etwas
anders angehen wenn man größere chunks holt.Bin mir nicht ganz sicher, ob ich verstanden habe was du meinst. Ich lese bisher in Chars ein, weil ich z.T. auf einzelne Bits zugreifen will. Meine ausgelesenen Werte haben Größen zwischen 1 Bit und 32 Byte und verschiedene Datentypen.
Bin mir nicht sicher ob es da sinnvoll ist, größere Chunks (= Blöcke?) einzulesen.
-
/* for(m=0;m<2;m++){ union_rechnen.c[m]=fgetc(FDatei); } */ fread(union_rechnen.c,sizeof(union_rechnen.c[0]),2,FDatei);
-
Achso. Du meinst so spar ich mir die for-Schleife?
-
Denk die Schleife ist dann in der Funktion. Wenn nun fgetc fread aufruft z.b.
fread(p_s,sizeof(char),1,fp); würds schon sinn machen. Abgesehen davon stubst nur
einmal das Os an und nicht in ner schleife.
-
Bin mir nicht sicher ob das wirklich einen Vorteil bringt.
Da wäre es doch eher sinnvoll sowas zu machen:union_rechnen.c[0] = fgetc(FDatei); union_rechnen.c[1] = fgetc(FDatei);
Bin mir nicht sicher, aber das sollte es ein wenig schneller machen...
-
Spreche jetzt mal nur für Linux. Die meißten wenn nicht sogar alle Funktionen aus der stdio.h
die mit dem Dateisystem arbeiten rufen intern syscall 3 oder 4 auf ne schöne tabelle gibts
hier http://bluemaster.iu.hio.no/edu/dark/lin-asm/syscalls.html
beide syscalls benötigen die Größe und Anzahl so wie bei fread.
-
Bin leider was Linux angeht noch relativ unbedarft. Mein Firmen-PC ist ein reiner XP-Rechner.
-
Ach normal macht windows intern doch das gleiche wie unix
-
[quote="Blue]
Ich lese ja nur aus, wenn ich auch was hineingeschrieben habe.
Mein Betreuer (das ganze hier ist ne Diplomarbeit) hat mich extra den Code umstellen lassen um die Unions zur Typkonvertierung zu nutzen. Er begründet das mit Rechenzeitvorteilen.
[/quote]
naja, aber auch wenns bei dir funktioniert, ist es unportabel und nur ein hack. ausserdem glaub ich kaum, dass es zu lahm wird, wenn du's richtig machst. compiler sind ganz oft schön schlau, erkennen bekannte codemuster (z.b. zusammenbau zweier byte zu 'nem 16-bit wert) und optimieren sowas ziemlich gut.