4x8Bit ins 1x32Bit

Gast #1183055
Die UND-Verknüpfungen kannst du dir sparen, da ein Byte sowieso nur max 
255 werden kann.....
1
#define BYTE4_TO_LONG(a,b,c,d)   (  ( ( (uint32_t)a) << 24))  + (  ( (uint32_t)b) << 16)  + ( ( (uint32_t)c) << 8)  + ( (uint32_t)d) )
Gast #1183089
>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.
Gast #1183096
> 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
unsigned long byte4_to_long (unsigned char a, 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.
Gast #1183097
>>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?
Gast #1183106
Halt! Fehler! Man muss die Daten vor dem Schieben auf 32 Bit bringen!
1
unsigned long byte4_to_long (unsigned char a, b, c, d)
2
{
3
    return (((((((unsigned long) a << 8) | b) << 8) | c) << 8) | d);
4
}

Sorry ...
Persönliche Seite #1183115
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
unsigned long foo (char c)
2
{
3
    return (unsigned long) c;
4
}
Wir demgemäß übersetzt zu
1
foo:
2
  mov r18,r24
3
  clr r19
4
  sbrc r18,7
5
  com r19
6
  mov r20,r19
7
  mov r21,r19
8
  movw r22,r18
9
  movw r24,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
#1183163
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
Persönliche Seite #1183339
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
Gast #1183382
>>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.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 17 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.