www.mikrocontroller.net

Forum: Compiler & IDEs 4x8Bit ins 1x32Bit


Autor: fantomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Abend, gehts noch kürzer?
  #define BYTE4_TO_LONG(a,b,c,d)   (  (((((uint32_t)a) << 24)) & 0xFF000000)  + (((((uint32_t)b) << 16)) & 0x00FF0000)  + (((((uint32_t)c) << 8)) & 0x0000FF00)  + (((uint32_t)d) & 0x000000FF) )
  

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Man könnte noch über eine union arbeiten. Aber bei beiden Methoden: 
Achte auf das Thema Endianess und auf den Unterschied signed/unsigned...

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die UND-Verknüpfungen kannst du dir sparen, da ein Byte sowieso nur max 
255 werden kann.....
#define BYTE4_TO_LONG(a,b,c,d)   (  ( ( (uint32_t)a) << 24))  + (  ( (uint32_t)b) << 16)  + ( ( (uint32_t)c) << 8)  + ( (uint32_t)d) )

Autor: fantomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hab mal irgendwo gelesen das man aus Sicherheit unden soll. Stimmt es?

Autor: Micha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was spricht gegen die Verwendung einer union?

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>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.

Autor: tuppes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> 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:
unsigned long byte4_to_long (unsigned char a, b, c, d)
{
    return ((((((a << 8) | b) << 8) | c) << 8) | d);
}
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.

Autor: tuppes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>>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?

Autor: tuppes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Halt! Fehler! Man muss die Daten vor dem Schieben auf 32 Bit bringen!
unsigned long byte4_to_long (unsigned char a, b, c, d)
{
    return (((((((unsigned long) a << 8) | b) << 8) | c) << 8) | d);
}

Sorry ...

Autor: Skua (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Wo steht, dass das Bytes sind?
Im Titel.


Aber findet der Typecast vor oder nach dem Speicherzugriff statt?
Ist das Normiert?

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.
unsigned long foo (char c)
{
    return (unsigned long) c;
}
Wir demgemäß übersetzt zu
foo:
  mov r18,r24
  clr r19
  sbrc r18,7
  com r19
  mov r20,r19
  mov r21,r19
  movw r22,r18
  movw r24,r20
  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

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: tuppes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>>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

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.