>hab mal irgendwo gelesen das man aus Sicherheit unden soll. Stimmt es?
Wenn du mir zeigst, das ein Byte größer als 0xFF sein kann, ja...
>Was spricht gegen die Verwendung einer union?
Nichts.
> Was spricht gegen die Verwendung einer union?
Grundsätzlich nichts, würde ich sagen. Welche der Varianten zum
kleinsten Code führt oder am wenigsten RAM verbraucht, ist vermutlich
stark plattformabhängig.
Wenn man in dem Makro oben die VerUNDung weglässt, begibt man sich auf
dünnes Eis, weil man dann unbemerkt auch Daten verwursten kann, die
größer als 8 Bit sind. Das führt dann zu unerwarteten Ergebnissen.
Aus dem Grund würde ich sowas als Funktion schreiben, da ist die
Typsicherheit besser:
1
unsignedlongbyte4_to_long(unsignedchara,b,c,d)
2
{
3
return((((((a<<8)|b)<<8)|c)<<8)|d);
4
}
Wer diese Funktion mit 16- oder 32-Bit-Argumenten füttert, bekommt
entweder eine Compiler-Warnung ("data truncation") oder stillschweigend
das richtige Ergebnis.
Aber auch hier gilt: Augen auf bei der Byte-Order.
>>hab mal irgendwo gelesen das man aus Sicherheit unden soll. Stimmt es?>Wenn du mir zeigst, das ein Byte größer als 0xFF sein kann, ja...
Wo steht, dass das Bytes sind?
Matthias Lipinsky wrote:
>>hab mal irgendwo gelesen das man aus Sicherheit unden soll. Stimmt es?>> Wenn du mir zeigst, das ein Byte größer als 0xFF sein kann, ja...
Delault für char ist signed.
1
unsignedlongfoo(charc)
2
{
3
return(unsignedlong)c;
4
}
Wir demgemäß übersetzt zu
1
foo:
2
movr18,r24
3
clrr19
4
sbrcr18,7
5
comr19
6
movr20,r19
7
movr21,r19
8
movwr22,r18
9
movwr24,r20
10
ret
Zudem steht zu vermuten, daß der riesige Ausdruck, den BYTE4_TO_LONG
erzeugt, nicht komplett auf der maschinenunabhängigen Ebene von gcc
behandelt wird. Bzw es wird mit den 0xff-Masken einfacher (obwohl der
Ausdruck komplexer ist) wenn man dem Compiler mit den Masken die Info
gibt, daß es sich bei den 32-Byte werten nur um verschobene Bytes
handelt. Er kann das zwar prinzipell wissen bzw. erkennen, aber irgendwo
ist eben Ende, wie weit die Analyse getrieben wird.
Aus dem Grunde sollte man das Makro auf jeden Fall auch mit | schreiben
anstsatt mit + ! Liefert hier zwar das gleiche, aber PLUS ist wesentlich
fieser als OR, weil ersteres die Bits durcheinanderwürfelt.
>>Was spricht gegen die Verwendung einer union?>> Nichts.
Der Union ist klar der Vorzug zu geben, sowohl was Lesbarkeit der Quelle
angeht, als auch was algebraische Darstellung im gcc angeht.
Johann
Johann L. wrote:
>>>Was spricht gegen die Verwendung einer union?>>>> Nichts.
Ne Menge!
Wenn es um den Datenaustausch mit anderen Systemen geht, sollte man
tunlichst auf ne Union verzichten, sonst krachts.
Und auch wenn der Code auf verschiedenen Compilern laufen soll.
Einige übliche Byteorders:
1, 2, 3, 4
2, 1, 4, 3
4, 3, 2, 1
3, 4, 1, 2
Peter
Peter Dannegger wrote:
> Johann L. wrote:>>>>>Was spricht gegen die Verwendung einer union?>>>>>> Nichts.>> Ne Menge!>> Wenn es um den Datenaustausch mit anderen Systemen geht, sollte man> tunlichst auf ne Union verzichten, sonst krachts.> Und auch wenn der Code auf verschiedenen Compilern laufen soll.
Davon war nix geschrieben. Jemand, der nen TCP/IP Stck implementiert,
ist sich glaub darüber im klaren, daß due Übertragung zwischen
Plattformen unterschiedlicher Endianess geschehen kann.
Die Union funktioniert für little Endian. Für big Endian macht sie was
anderes als das Makro -- auch ohne Kommunikation.
Johann
>>Wo steht, dass das Bytes sind?>Im Titel.
Ächz. Ich meinte: Wo in dem Makro ist das für den C-Compiler
erkennbar?
Antwort: Gar nicht, d.h. er hat keine Chance, zu erkennen, wenn das
Makro irrtümlich mit einem 16- oder 32-Bit-Wert aufgerufen wird.
> Aber findet der Typecast vor oder nach dem Speicherzugriff statt?> Ist das Normiert?
Du meinst, ob das a 8- oder 32-bittig aus der Quelle (Stack?) geholt
wird? Das kann der Compiler prinzipiell machen, wie er will, aber er
muss es konsistent machen, also das Datum so vom Stack runterholen, wie
es vor dem Function-Call draufgepusht wurde.