PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [ERLEDIGT] #pragma pack(1) Problem



Siro
21.09.2011, 16:03
Hallo zusammen,
darf ich das hier fragen, geht ja nicht direkt um ATMEL aber ich denke mal es betrifft alle C-Compiler...
Laut Hilfe kann ich mit der Direktive #pragma pack(1) dem Compiler mitteilen, daß er meine Daten entsprechend dem Klammerausdruck packen soll.
Also wen ich pack(1) angebe müsten die Daten meiner Meinung nach Byteweise gepackt werden. Damit keine unnötigen Löcher im Speicher entstehen.
Wenn ich mir den Mapfile ansehe wird für meine angelegten Variablen aber trotzdem mehr Speicher reserviert als nötig.
Dazu ein Beispiel:

#pragma pack(1) /* align the structure to bytes */
char name[5]
#pragma pack() /* end of packed structure */

Für meine Variable "name" werden laut Mapfile 8 Bytes statt 5 reserviert.
Wenn ich die sizeof Funktion benutze, wird aber korrekterweise 5 zurückgeliefert. Warum reserviert er dann 8 Bytes ? Das wollte ich doch durch pack(1) verhindern.

Ist das bei anderen Compilern auch so, oder habe ich die pack direktive vielleicht nicht richtig verstanden ?
Für Informationen wäre ich Euch dankbar.
Siro

PicNick
22.09.2011, 08:09
Wesentlich ist, wo der Compiler die nächste Variable hinlegt.
NACH pack() wird der Compiler die nächste Variable wieder "alignen", d.h. du hast eigentlich von dem ganzen nix.

Probiere und prüfe dann:


#pragma pack(1)
char name[5];
char addr[13];
char plz[5];
#pragma pack()

da darf dann zwischen den Variablen keine Lücke sein.





Abgesehen von allem Anderen, solltest du das so machen: (wenn der Compiler mitspielt)


#pragma pack(push)
#pragma pack(1)
------
#pragma pack(pop)

Der Sinn liegt auf der Hand (bei verschachtelten ".H" files

Siro
23.09.2011, 16:15
Hallo PicNick,
erst einmal Danke für deine Antwort,

ich hab das grad mal ausprobiert und dachte ich träume. Nach welchen Kriterien legt denn mein Compiler die Variablen an ?????
Schau Dir mal die Adressen laut Mapfile an, da fällt man doch vom Glauben ab.

#pragma pack(1)
char name[5]; /* Adresse laut Mapfile: 6A5C 8 Bytes reserviert, sizeof liefert 5 */
char addr[13]; /* Adresse laut Mapfile: 6A24 16 Bytes reserviert, sizeof liefert 13 */
char plz[5]; /* Adresse laut Mapfile: 6A64 8 Bytes reserviert, sizeof liefert 5 */
#pragma pack()

Sizeof liefert aber immer die richtige Größe.

Hab dann mal folgendes probiert:

name[1] Compiler reserviert 1 Byte
name[2] Compiler reserviert 2 Byte
name[3] Compiler reserviert 4 Byte
name[4] Compiler reserviert 4 Byte
name[5] Compiler reserviert 8 Byte
name[6] Compiler reserviert 8 Byte
name[7] Compiler reserviert 8 Byte
name[8] Compiler reserviert 8 Byte
name[9] Compiler reserviert 12 Byte
name[12] Compiler reserviert 12 Byte
name[13] Compiler reserviert 16 Byte

Meiner Meinung nach funktioniert PACK überhaupt nicht. Hab aber grad gelesen, daß das pack NUR nur in Verbindung mit struct funktioniert. Kann das sein ???
Mit dem (push) und (pop) beim pack scheint mir eine gute Sache zu sein, das unterstützt mein IAR Compiler auch.
Ich kann das wohl auch so schreiben, wenn ich das richtig verstanden habe.
#pragma pack(push,1) und am Ende dann #pragma(pop) Deine Variante akzeptiert er aber auch.

Nun aber ab ins Wochenende,
Siro

PicNick
23.09.2011, 16:28
Naja, ich verwend' es nur bei Daten-strukturen, denn da müssen die Daten ja geschlossen u. lückenlos definiert sein.

Das mit dem "nur mit struct" könnt' schon sein, denn ausserhalb von struct legt der Compiler die Variablen offenbar dort an, wo es ihm gerade einfällt. (alphabetisch?). Ich weiss jetzt garnicht, ob es einen Anspruch darauf gibt, dass der Kompiler die Variablen in der Folge anlegt, wie die angegeben werden ?
Das ist von akademischen Interesse, daher würd ich an deiner stelle, damit was weitergeht, eben eine struct konstruieren, wo die Variablen drin stehen, die ich beieinander haben möchte. da hat der Kompiler dann keine Ausflüchte.

Dass "sizeof" richtige Werte liefert, wundert mich nicht, denn, ich schwör's, das wär schon aufgefallen.

Aber wer checkt schon, an welcher Adresse seine Variablen liegen, und ob es dazwischen Lücken gibt.
(Natürlich µC Programmierer, denn die müssen jedes Byte zweimal umdrehen, bevor sie es belegen :-) )

Siro
23.09.2011, 16:58
Im struct scheint es richtig zu funktionieren. Er belegt jedoch trotzem teilweise mehr Bytes. Er scheint die Strukturen auf 4 Bytes zu "Alignen" vermutlich wegen der 32 Bit Struktur des verwendeten Prozessor.
Und ja, ich drehe jedes Byte immer 2 mal um, oder dreimal, bevor ich es ver(sch)wende. :-) Früher zumindest bei den 8 Bittern, jetzt eigentlich weniger der LPC1768 hat ja reichlich RAM.

Hab es nun so probiert:

#pragma pack(push,1)
struct
{
char name[5];
char addr[13];
char plz[5];
} t;
#pragma pack(pop)

Das kann aber unter Umständen zu ineffektiven Code führen, wenn man auf ungrade Adressen innerhalb der Struktur zugreift. Wenn man also genügend Speicher hat, sollte man lieber dem Compiler die Arbeit überlassen,
und pack ganz weglassen, denke ich.
Siro

Felix G
23.09.2011, 20:59
Im struct scheint es richtig zu funktionieren. Er belegt jedoch trotzem teilweise mehr Bytes. Er scheint die Strukturen auf 4 Bytes zu "Alignen" vermutlich wegen der 32 Bit Struktur des verwendeten Prozessor.Ja, das ist sehr oft so. Ich z.B. habe beruflich mit Blackfin DSPs von Analog Devices zu tun, und wenn man da versehentlich mal auf eine nicht durch 4 teilbare Addresse zugreift, stürzt der DSP sofort mit einer Exception ab.

Bei #pragma pack geht es übrigens in erster Linie nicht darum Speicher zu sparen, sondern darum ein ganz bestimmtes vorgegebenes Speicherlayout zu erzielen. Das kann insbesondere bei der Kommunikation wichtig sein. Ein Beispiel wäre etwa ein Ethernet Frame, bei dem ja ganz genau vorgegeben ist wie es aussehen muss, und da wäre es extrem kontraproduktiv, wenn so eine Struktur im Speicher irgendwelche Lücken hätte.