Typumwandlung mit Union fehlerhaft?



  • 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.
    🙂



  • Was ist daran unportabel? Und wieso hack?



  • Blue][ce schrieb:

    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...

    Im Gegenteil, es führt zu schlechter Performance, Daten aus dem OS- Filesystem charweise zu holen.
    Ist mir drastisch vor Augen geführt worden, als ich 'ne ASM- Routine ausm Controller unter XP nach C portiert und den Stream zur Simulation aus 'ner Datei geholt habe. Einzelne chars abzuholen und zusammenzubasteln kostet irre Rechenzeit. Bei kleinen Testdatensätzen war's wurscht, weil einem nicht auffällt, ob das Ding 0,1 oder 0,3 Sekunden läuft, bei großen Datenmengen spielt es dann schon eine Rolle, ob das Ding eine halbe oder anderthalb Minuten vor sich hinrattelt.
    Nach Umpacken in eine Struct hat das Ding um Faktor 3 an Tempo zugelegt, ist zwar nur exemplarisch, dürfte sich aber allgemein in der Größenordnung bewegen. Also byteweise vom Filesystem zu lesen, ist ein echter Performancekiller ⚠

    Und die Typkonvertierung über 'ne Union zu machen hat sowieso die von fricky dargelegten Nachteile, so ^^^^^^ würdest Du alle Nachteile vereinen. 🙄



  • Blue][ce schrieb:

    Was ist daran unportabel? Und wieso hack?

    Unportabel deshalb, weil nicht eindeutig festgelegt ist, wie der Compiler seine unions und structs zu organisieren hat. Mit pack- pragmas kannst Du z.B. verschiedene Alignments erzwingen. Heißt, Du kannst nicht davon ausgehen, daß die gleiche Source auf verschiedenen Systemen die gleichen Daten erzeugt, die physikalisch auf Platte landen.
    Noch eine Möglichkeit des Schiefgehens bietet die Little/BigEndian- Problematik.

    So ziemlich alles, was die Source an eine ganz bestimmte Compiler/HW-Plattform- Kombination bindet, bezeichnet man als Hack. In C löst man solche Sachen besser über defines auf, die explizit die Unterschiede klarmacht und schafft sich keine Probleme durch zunächst augenscheinlich unauffällige Codestückchen mitten in der Source.


Anmelden zum Antworten