Forum: PC-Programmierung little zu big endian funktioniert nicht


von Maxim (maxim) Benutzerseite


Lesenswert?

Ich muss von little zu big endian auf dem PC konvertieren. Dazu habe ich 
zwei Funktionen:
1
int swapBytes(int dataIn) {
2
  int dataOut;
3
  char *in = (char*)&dataIn, *out = (char*)&dataOut;
4
  for(int i = 0; i < 3; i++) {out[i] = in[3 - i];}
5
  return dataOut;
6
}
7
8
#define swap32(x) \
9
((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >>  8) | (((x) & 0x0000ff00) <<  8) | (((x) & 0x000000ff) << 24))

Die Precompiler-Funktion funktioniert richtig. Aber swapBytes() gibt 
immer 0 zurück. Woran liegt das?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Falls du GCC verwendest: Es gibt __builtin_bswap32

http://gcc.gnu.org/onlinedocs/gcc-4.6.3/gcc/Other-Builtins.html#index-g_t_005f_005fbuiltin_005fbswap32-3181

Allerdings nur dann, wenn man das Rad nicht neu erfinden will.

von Maxim (maxim) Benutzerseite


Lesenswert?

Das weiß ich. Diese funktion lässt sich aber nicht auf float anwenden. 
Ich benötige aber Konvertierung sowohl für int als auch für float.

von Peter II (Gast)


Lesenswert?

Maxim S. schrieb:
> Das weiß ich. Diese funktion lässt sich aber nicht auf float anwenden.
> Ich benötige aber Konvertierung sowohl für int als auch für float.

nein das brauchst du kann bestimmt nicht. Float muss nicht gedreht 
werden. Den fehler hatten wir vor kurzen schon mal hier, das jemand 
versucht hat ein float zu drehen - der Fehler lag woanders.

von Maxim (maxim) Benutzerseite


Lesenswert?

Peter II schrieb:
> Maxim S. schrieb:
>> Das weiß ich. Diese funktion lässt sich aber nicht auf float anwenden.
>> Ich benötige aber Konvertierung sowohl für int als auch für float.
>
> nein das brauchst du kann bestimmt nicht. Float muss nicht gedreht
> werden. Den fehler hatten wir vor kurzen schon mal hier, das jemand
> versucht hat ein float zu drehen - der Fehler lag woanders.

Ein float lässt sich so drehen:
1
float swapBytes(float dataIn) {
2
  float dataOut;
3
  char *in = (char*)&dataIn, *out = (char*)&dataOut;
4
  for(int i = 0; i < 3; i++) {out[i] = in[3 - i];}
5
  return dataOut;
6
}

Ein int lässt sich auf diese Weise aber nicht drehen. Dafür kann man 
einen float nicht mit Bitoperationen drehen, da diese hier gar nicht 
anwendbar sind.

von Peter II (Gast)


Lesenswert?

Maxim S. schrieb:
> Peter II schrieb:
>> Maxim S. schrieb:
>>> Das weiß ich. Diese funktion lässt sich aber nicht auf float anwenden.
>>> Ich benötige aber Konvertierung sowohl für int als auch für float.
>>
>> nein das brauchst du kann bestimmt nicht. Float muss nicht gedreht
>> werden. Den fehler hatten wir vor kurzen schon mal hier, das jemand
>> versucht hat ein float zu drehen - der Fehler lag woanders.
>
> Ein float lässt sich so drehen:

ja, aber aus welchen Grund?
Ein float ist auf big und Little endian gleich.

von Maxim (maxim) Benutzerseite


Lesenswert?

Peter II schrieb:
> Ein float ist auf big und Little endian gleich.

Das stimmt im Allgemeinen nicht.

von Peter II (Gast)


Lesenswert?

Maxim S. schrieb:
> Peter II schrieb:
>> Ein float ist auf big und Little endian gleich.
>
> Das stimmt im Allgemeinen nicht.

wo stimmt das denn nicht?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Maxim S. schrieb:
> Das weiß ich. Diese funktion lässt sich aber nicht auf float anwenden.
> Ich benötige aber Konvertierung sowohl für int als auch für float.

Um die Binärdarstellung von float zu bekommen, nimm memcpy. GCC 
optimiert das weg.

von Peter II (Gast)


Lesenswert?

Johann L. schrieb:
> Maxim S. schrieb:
>> Das weiß ich. Diese funktion lässt sich aber nicht auf float anwenden.
>> Ich benötige aber Konvertierung sowohl für int als auch für float.
>
> Um die Binärdarstellung von float zu bekommen, nimm memcpy. GCC
> optimiert das weg.

wie willst du mit memcpy an eine Binärdarstellung rankommen? memcpy 
kopiert nur Byte von a nach b - es sind immer noch die gleichen bits in 
de gleichen Reihenfolge.

von Martin H. (marrtn)


Lesenswert?

Falls die Endianess tatsächlich gedreht werden müsste und kein 
MISRA-Checker vorbei kommt, würde ich ganz brutal casten ;-)
1
float a = 87654.321;
2
int b = __builtin_bswap32(*((int *) &a));

bzw. andersherum
1
int a = __builtin_bswap32(irgendeineQuelleMitFalscherEndianess());
2
float b = *((float *) &a));

: Bearbeitet durch User
von <= (Gast)


Lesenswert?

Maxim S. schrieb:
> for(int i = 0; i < 3; i++)

for(int i = 0; i <= 3; i++)

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Peter II schrieb:
> Johann L. schrieb:
>> Maxim S. schrieb:
>>> Das weiß ich. Diese funktion lässt sich aber nicht auf float anwenden.
>>> Ich benötige aber Konvertierung sowohl für int als auch für float.
>>
>> Um die Binärdarstellung von float zu bekommen, nimm memcpy. GCC
>> optimiert das weg.
>
> wie willst du mit memcpy an eine Binärdarstellung rankommen? memcpy
> kopiert nur Byte von a nach b - es sind immer noch die gleichen bits in
> de gleichen Reihenfolge.

Genau darum geht es.  Wenn man ein float in eine Funktion steckt, die 
ein int erwartet, gibt's eine implizite Umwandlung nach int.  Das will 
der TO hier offenbar nicht.

von Peter II (Gast)


Lesenswert?

Johann L. schrieb:
> Das will
> der TO hier offenbar nicht.
er will die Byte von einen float drehen, das alleine ist schon 
merkwürdig.

von Maxim (maxim) Benutzerseite


Lesenswert?

<= schrieb:
> Maxim S. schrieb:
>> for(int i = 0; i < 3; i++)
>
> for(int i = 0; i <= 3; i++)

Tatsächlich, da war ein Fehler. Da die floats aber alle nicht größer als 
1.0 sind, hat das trotzdem noch funktioniert. ;) Danke.

Peter II schrieb:
> Johann L. schrieb:
>> Das will
>> der TO hier offenbar nicht.
> er will die Byte von einen float drehen, das alleine ist schon
> merkwürdig.

Ich muss die Bytes von floats tatsächlich drehen, weil das 
VTK-Dateiformat das so haben möchte. Mittlerweile funktioniert es auch 
und zwar so:
1
float swapBytes(float dataIn) {
2
  float dataOut;
3
  char *in = (char*)&dataIn, *out = (char*)&dataOut;
4
  for(int i = 0; i < 3; i++) {out[i] = in[3 - i];}
5
  return dataOut;
6
}

Die gleiche Funktion für int funktioniert aber nicht. Da benutze ich 
dann die Bitoperatoren.

von Antworter (Gast)


Lesenswert?

Maxim S. schrieb:
>for(int i = 0; i < 3; i++)
> Die gleiche Funktion für int funktioniert aber nicht.

Liest du überhaupt Antworten?

<= schrieb:
> for(int i = 0; i <= 3; i++)

von Simon K. (simon) Benutzerseite


Lesenswert?

char ist nicht zwangsläufig 1 Byte groß... Und float nicht zwangsläufig 
32 Bit.

: Bearbeitet durch User
von Rolf Magnus (Gast)


Lesenswert?

<= schrieb:
> Maxim S. schrieb:
>> for(int i = 0; i < 3; i++)
>
> for(int i = 0; i <= 3; i++)

Da würde ich eher die übliche Schweibweise bevorzugen:
1
for(int i = 0; i < 4; i++)

Simon K. schrieb:
> char ist nicht zwangsläufig 1 Byte groß...

Doch, ist es.

> Und float nicht zwangsläufig 32 Bit.

Statt 4 könnte man besser sizeof(float) nehmen.

von Kaj (Gast)


Lesenswert?

Rolf Magnus schrieb:
> Simon K. schrieb:
>> char ist nicht zwangsläufig 1 Byte groß...
>
> Doch, ist es.

Nö. Gibt genug Plattformen wo char größer als 1 Byte ist.

von Dr. Sommer (Gast)


Lesenswert?

Kaj schrieb:
> Nö. Gibt genug Plattformen wo char größer als 1 Byte ist.
char ist per Definition 1 Byte groß. Aber 1 Byte ist nicht 
notwendigerweise 8 bits (per Standard)... Die Frage enthielt aber "PC" 
was x86 und damit 8-Bit-Bytes nahelegt.

von Rolf Magnus (Gast)


Lesenswert?

Kaj schrieb:
> Gibt genug Plattformen wo char größer als 1 Byte ist.

Dann sind die kaputt. Aus ISO C:

******************************************
The sizeof operator yields the size (in bytes) of its operand, which may 
be an expression or the parenthesized name of a type.

When applied to an operand that has type char, unsigned char, or signed 
char, (or a qualified version thereof) the result is 1.
******************************************

von Mark B. (markbrandis)


Lesenswert?

Ich denke damit ist gemeint, dass es Prozessoren gibt, die einfach von 
ihrer Architektur her niemals weniger bearbeiten können als 16 (oder 32 
etc.) Bits auf einmal. Ist halt nicht jeder ein x86 und hat AL, AX, EAX 
und wie sie alle heißen.

Trifft meines Wissens nach zum Beispiel auf diverse DSP zu.

Hat es einen besonderen Sinn, so zu tun als ob ein char zwangsläufig aus 
einem Byte besteht? Ein Byte besteht nun mal in aller Regel aus 8 Bits - 
wir sind hier nicht auf einer PDP ;-)

: Bearbeitet durch User
von Rolf Magnus (Gast)


Lesenswert?

Mark Brandis schrieb:
> Ich denke damit ist gemeint, dass es Prozessoren gibt, die einfach von
> ihrer Architektur her niemals weniger bearbeiten können als 16 (oder 32
> etc.) Bits auf einmal. Ist halt nicht jeder ein x86 und hat AL, AX, EAX
> und wie sie alle heißen.
>
> Trifft meines Wissens nach zum Beispiel auf diverse DSP zu.

Genau. Die gibt es auch z.B. 24 Bits.

> Hat es einen besonderen Sinn, so zu tun als ob ein char zwangsläufig aus
> einem Byte besteht?

Man "tut" nicht "so", sondern definert es. Ein Mathematiker tut ja auch 
nicht so, als sei + das Zeichen für die Addition, sondern bestimmt halt, 
daß es so ist.

> Ein Byte besteht nun mal in aller Regel aus 8 Bits - wir sind hier nicht
> auf einer PDP ;-)

Ein Byte besteht in der Regel aus der kleinsten adressierbaren Einheit, 
und die ist gerade auf besagten DSPs dann eben nicht 8 Bit groß.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.