Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » Zur Endian-problematik

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 <
000
18.10.2004, 13:15 Uhr
Hans
Library Walker
(Operator)


Hi,

ich hab mir bezüglich des Endianproblems bei der Bitbetrachtung von Daten mal so ein paar Gedanken gemacht. Dabei kam ich auf folgende Idee (s.u.), um das Problem zu lösen. Die Frage ist nur, ob das Ding auch so funktioniert. Bei mir auf dem Intel-Prozessor läuft es, aber wie sieht es auf 'nem Motorola-Prozessor aus?

C++:
#include <stdio.h>

union Zahl
{
   int I;
   long L;
   float F;
   double D;
   long double LD;
   char c[sizeof(long double)];
} Z;

void zahlaus();

int main(int argc, char **argv)
{
  int i;
  int flag;

  for (i=0; i<=sizeof(long double); i++)
       Z.c[i] = '\0';

  Z.I = 65536;

  if (sizeof(int)==2)    /* Test für 16 Bit System */
    { if(Z.c[1]==1) flag = 0; /* flag = 0 => Little Endian */
      else flag = 1;           /* flag = 1 => Big Endian */
    }
  else if (sizeof(int)==4)    /* Test für 32 Bit System */
    { if(Z.c[1]==1) flag = 0;
      else flag = 1;
    }

  Z.I = 1;
  printf ("Z.I = %d\t", Z.I);
  zahlaus();
  printf ("\n");

  Z.I = 65536;
  printf ("Z.I = %d\t", Z.I);
  zahlaus();
  printf ("\n");

  Z.LD = -1.0;
  printf ("Z.LD = %4.2Lf\t", Z.LD);
  zahlaus();
  printf ("\n");

  for (i=0; i<=sizeof(long double); i++)
      Z.c[i] = 0xff;
  printf ("Z.LD = %Lf\t", Z.LD);
  zahlaus();
  printf ("\n");

  printf ("System arbeitet mit %s-Endian Byte-order.\n", flag ? "little" : "big");

  return 0;
}

void zahlaus()
{
  int i;

  for (i=0; i<=sizeof(long double)+1; i++)
    { if (i%4 == 0)
         printf (" ");
      printf ("%02x ", Z.c[i]&255); /* Ausgabe auf 8 bit beschränken. Das x ist ja
                           für int, und da eine implizite
                           Typenkonvertieung vorgenommen wird, werden
                           32Bit, bzw. 8 Hex-ziffern ausgegeben wenn
                           ein int grösser als 255 ist. */

    }
  return;
}



Die Ausgabe sieht bei mir so aus:

Code:
D:\borland\CBuilder\Projects>byteordertest
Z.I = 1  01 00 00 00  00 00 00 00  00 00 00 00
Z.I = 65536      00 00 01 00  00 00 00 00  00 00 00 00
Z.LD = -1.00     00 00 00 00  00 00 00 80  ff bf 00 00
Z.LD = -NAN      ff ff ff ff  ff ff ff ff  ff ff ff 00
System arbeitet mit little-Endian Byte-order.


Wäre gut, wenn mal jemand die Ausgabe eines PowerPC, oder sonstigen Rechners der mit Motorola-CPU arbeitet hier posten könnte.

Hans
--
Man muss nicht alles wissen, aber man sollte wissen, wo es steht. Zum Beispiel hier: Nachdenkseiten oder Infoportal Globalisierung.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
18.10.2004, 13:21 Uhr
Hans
Library Walker
(Operator)


Ups, mist, da ist ja noch ein Fehler drin, wieso seh ich den denn jetzt erst??

Naja, dann kann mir ja vielleicht jemand sagen, ob der Ansatz nicht sowieso einen grundsätzlichen Haken hat.

Hans
--
Man muss nicht alles wissen, aber man sollte wissen, wo es steht. Zum Beispiel hier: Nachdenkseiten oder Infoportal Globalisierung.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
18.10.2004, 13:33 Uhr
virtual
Sexiest Bit alive
(Operator)


Hm, also den Endiantest finde ich persönlich etwa umständlich. Ich würde es so machen (läuft bei eigentlich allen nennenswerten Platformen:

C++:
int is_bigendian() { return htons(0x1234) == 0x1234; }



Die Übertragung von long double ist generell - wie bei allen Floats - implementationsabh. , der Standard setzt hier keine genauen Größen fest. Wenn es um die plattform unabh. Übertragung solcher Größen geht, macht man es am besten wie der XDR Layer bei RPC/Corba und anderen: Das float/double in Seine componenten (Mantisse, Exponent, vorzeichen) aufspalten. Dies sind für sichgenommen integer und können wieder mit htonl /ntohl behandelt werden.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)

Dieser Post wurde am 18.10.2004 um 13:34 Uhr von virtual editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
18.10.2004, 18:14 Uhr
Hans
Library Walker
(Operator)



Zitat von virtual:
Hm, also den Endiantest finde ich persönlich etwa umständlich.

Nun ja, ein kluger Mensch hat einmal behauptet, das eine Entwicklung immer vom Umständlichen übers Abstrakte zum einfachen verläuft...

Zitat von virtual:
Das float/double in Seine componenten (Mantisse, Exponent, vorzeichen) aufspalten. Dies sind für sichgenommen integer und können wieder mit htonl /ntohl behandelt werden.

Okay, das Mantisse, Exponent und Vorzeichen für sich genommen integer sind, leuchtet ein. Aber wo sind htonl /ntohl deklariert? In der Hilfe von meinem C++ Builder (5.5) steht dazu jedenfalls nichts. Sind die womöglich aus C99?

Hans
--
Man muss nicht alles wissen, aber man sollte wissen, wo es steht. Zum Beispiel hier: Nachdenkseiten oder Infoportal Globalisierung.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
18.10.2004, 18:41 Uhr
ao

(Operator)



Zitat von Hans:
Aber wo sind htonl /ntohl deklariert? In der Hilfe von meinem C++ Builder (5.5) steht dazu jedenfalls nichts. Sind die womöglich aus C99?

Irgendwo im Dunstkreis von Sockets / Winsock oder so.

ao
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
18.10.2004, 20:06 Uhr
(un)wissender
Niveauwart


Kannst dir auch selber schreiben.


C++:
#include <iostream>
#include <algorithm>

union Endian
{
    Endian():digit(0xFF000000) {}
    unsigned digit;
    unsigned char test[];
};

Endian endian;

bool isLittleEndian()
{
    return (endian.test[0] == 0x00);
}

bool isBigEndian()
{
    return !isLittleEndian();
}

unsigned htonl(unsigned digit)
{
    if(isBigEndian())
        return digit;
    Endian end;
    end.digit = digit;
    std::swap(end.test[3], end.test[0]);
    std::swap(end.test[2], end.test[1]);
    return end.digit;
}



int main()
{
    if(isLittleEndian())
        std::cout << "little" << std::endl;
    else
        std::cout << "big" << std::endl;

    std::cout << endian.digit << " " << htonl(endian.digit) << std::endl;
        
    return 0;

}




Bearbeitung:

Der geneigte Leser passe dies auch für nicht 32Bit Systeme an.


--
Wer früher stirbt ist länger tot.

Dieser Post wurde am 18.10.2004 um 20:20 Uhr von (un)wissender editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
18.10.2004, 21:32 Uhr
~mike
Gast


Hi!
Auf nem Apple G4

Zitat:

Z.I = 1 00 00 00 01 00 00 00 00 00 00
Z.I = 65536 00 01 00 00 00 00 00 00 00 00
Z.LD = -1.00 bf f0 00 00 00 00 00 00 00 00
Z.LD = nan ff ff ff ff ff ff ff ff ff 00
System arbeitet mit big-Endian Byte-order.



mfg
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
18.10.2004, 21:48 Uhr
~mike
Gast


Hi!
Hier noch ne Möglichkeit (von pronix)

C++:
#include <stdio.h>
typedef unsigned int  WORD;
typedef unsigned char BYTE;

int main()
{
   /* Word in den Speicher schreiben */
   WORD Word = 0x22CCDDEE;
   /* Zeiger auf ein Byte  */
   BYTE *Byte;

   /* Word-Zeiger auf Byte-Zeiger casten */
   Byte = (BYTE *) &Word;

/* Speicherinhalt nach Adressen von links nach rechts
* ausgeben.
* byte[0]byte[1]byte[2]byte[3]
* 22     CC     DD     EE       Speicherinhalt bei Little-Endian
* EE     DD     CC     22       Speicherinhalt bei Big-Endian
*/

   /* Ist Byte[0] == 11 */
   if(Byte[0] == ((Word >>  0) & 0xFF))
      printf("Little-Endian Architecture\n");
   /* oder ist Byte[0] == CC */
   if(Byte[0] == ((Word >> 24) & 0xFF))
      printf("Big-Endian Architecture\n");
   return 0;
}



mfg
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
008
19.10.2004, 19:34 Uhr
Hans
Library Walker
(Operator)


@mike:
Thank's für den Apple-output. Das Programm von Pronix sieht auch interessant aus; muss ich mir noch mal genauer ansehen.

@virtual:
Es hat 'n bischen gedauert, bis ich Deine htons-Methode kapiert habe...
Aber ich frage mich ernsthaft, ob es eine so gute Idee ist, Sockets und den ganzen Rattenschwanz einer Netzwerkanbindung in ein Programm einzubinden, das mit einem Netzwerk überhaupt nichts zu tun hat, weil es gar keine Netzwerksfunktionalität benötigt.

Zitat von virtual:
Das float/double in Seine componenten (Mantisse, Exponent, vorzeichen) aufspalten. Dies sind für sichgenommen integer

Wie nennen sich diese Funktionen, und wo finde ich die?? - Das klingt interessant genug, um damit auch mal so ein wenig zu experimentieren. Auch wenn man es gerade nicht benötigt

Hans
--
Man muss nicht alles wissen, aber man sollte wissen, wo es steht. Zum Beispiel hier: Nachdenkseiten oder Infoportal Globalisierung.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
009
19.10.2004, 19:43 Uhr
Windalf
Der wo fast so viele Posts wie FloSoft...
(Operator)


@Hans
es gibt auch noch ne schön knackige kurze beefy-Lösung dazu...
www.fun-soft.de/showtopic.php?threadid=4006
--
...fleißig wie zwei Weißbrote
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 <     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: