Forum: Mikrocontroller und Digitale Elektronik Frage zur Speicherverwaltung mittels struct


von brechbunkt (Gast)


Lesenswert?

Hallo,

ich habe die nachfolgende Struktur und mir ist wichtig, dass die 
Variablen dann auch tatsächlich genau so im Speicher angeordnet werden.

Richtiger weise schreibt meine 32-Bit-CPU die erste Variable (bfType) ab 
Adresse "Null". Diese Zahl ist dann 2 Byte lang.
Was ich nicht möchte ist, dass sie die nächsten 2 Byte einfach links 
liegen lässt (was aber der Fall ist).
Erst die danach folgenden 4 Bytes bekommen Werte meiner Variable bfSize 
zugewiesen.
1
typedef struct
2
{
3
    unsigned short bfType;
4
    unsigned int   bfSize;
5
    unsigned short bfReserved1;
6
    unsigned short bfReserved2;
7
    unsigned int   bfOffBits;
8
} myStruc_t;

Gibt es eine Möglichkeit die CPU (bzw. den compiler) dazu zu zwingen, 
dass er meine zweite Variable (bfSize) auf jedem Fall an der dritten 
Byteadresse speichern muss?
Bitfelder zu definieren bringt ja auch nichts, da die vom compiler 
angeordnet werden dürfen wie er möchte.

von Oliver J. (skriptkiddy)


Lesenswert?

gcc:
1
__attribute__ ((__packed__))

Beachte aber das Alignment. Bei einem ARM-Prozessor bekommst du damit 
unter Umständen Probleme.

Gruß Oliver

von (prx) A. K. (prx)


Lesenswert?

Oliver J. schrieb:
> Beachte aber das Alignment. Bei einem ARM-Prozessor bekommst du damit
> unter Umständen Probleme.

Funktionieren wird es bei direkten Zugriffen, da der Compiler um das 
falsche Alignment weiss. Alignment-Probleme entstehen dort, wo er es 
nicht weiss (Pointer).

Problemlos:
  return s.bfSize;
Problem:
  unsigned *p = &s.bfSize; // keine(!) Warnung
  return *p; // je nach Core kann das in die Hose gehen

PS: Bezieht sich auf GCC mit "packed". Portabel ist so etwas nicht. Mit 
Bitfeldern vermeidet man immerhin den Problemfall.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Bitfelder bringen u.U. aber ganz andere Probleme, insbesondere wenn 
irgendwo ein volatile in der Nähe ist...

Falls du selbst das struct-Layout festlegst (sieht bei dem Layout ganz 
danach aus), dann mach das so, daß es keine Lücken gibt.  Beispiel:
1
typedef struct
2
{
3
    unsigned int   bfSize;
4
    unsigned int   bfOffBits;
5
    unsigned short bfType;
6
    unsigned short bfReserved1;
7
    unsigned short bfReserved2;
8
} myStruc_t;

von Hmm (Gast)


Lesenswert?

>Bitfelder bringen u.U. aber ganz andere Probleme, insbesondere wenn
irgendwo ein volatile in der Nähe ist...

Magst Du das mal ein wenig näher beleuchten, Johann? Ich bin sicher das 
interessiert viele.

von (prx) A. K. (prx)


Lesenswert?

Siehe http://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html unter 
-fstrict-volatile-bitfields. Wobei das ein recht heiss diskutiertes 
Thema zu sein scheint. Wär wohl besser, sich in der Frage volatiler 
Bitfelder nicht zu sehr auf den Compiler zu verlassen.

von Udo S. (urschmitt)


Lesenswert?

Normalerweise hat man ein falsches Design, wenn man meint solche 
absoluten Adresspositionen zu brauchen.
Im Zweifel kann man noch 'padding' Variablen einfügen, die sicher dafür 
sorgen, daß die wichtigen Variablen fest auf durch 2/4/8 teilbaren 
Adressen beginnen.
Im allgemeinen sind solche Konstruktionen aber Scheiße, da sollte man 
lieber mal die Performance-Keule im Schrank lassen und eine 
Konvertierungsfunktion schreiben.

von brechbunkt (Gast)


Lesenswert?

Oliver J. schrieb:
> gcc:__attribute__ ((_packed_))
>
> Beachte aber das Alignment. Bei einem ARM-Prozessor bekommst du damit
> unter Umständen Probleme.
>
> Gruß Oliver

Ich danke sehr für die Antworten. Der Hinweis vom Oliver war super, 
jetzt funktioniert es.

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.