Forum: Compiler & IDEs pragma pack(1) funktioniert nicht


von Geri (Gast)


Lesenswert?

Hallo


sizeof(DC) liefert mir unter gcc auf einem ARM LPC1768 compiliert eine 
Länge von 70 Byte. Bisher waren es 62 Byte.

GNU Tools ARM Embedded\7 2017-q4-major
1
DataPacket.DataLen  = sizeof(DC); 
2
3
#pragma pack(1)
4
typedef struct
5
{
6
  uint16_t HardwareMajorVersion;
7
  uint16_t HardwareMinorVersion;
8
  uint16_t FirmwareMajorVersion;
9
  uint16_t FirmwareMinorVersion;
10
  uint8_t AxCnt;
11
  uint32_t CpuClockRate;
12
  uint8_t CpuName[12];
13
  uint32_t FifoBufSize;
14
  uint8_t CompilationDate[22];
15
  uint8_t FirmwareName[11];
16
}TDeviceContext;
17
#pragma pack()

Habe bereits in der gcc Dok gelesen, allerlei andere Direktive versucht 
jedoch keine Besserung.

Habt ihr vielleicht eine Idee wie man den Compiler dazu bewegt die 
Struktur zu packen?

Vielen Dank und beste Grüße
Geri

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Geri schrieb:
> Habt ihr vielleicht eine Idee wie man den Compiler dazu bewegt die
> Struktur zu packen?
1
typedef struct
2
{
3
  uint16_t HardwareMajorVersion;
4
  uint16_t HardwareMinorVersion;
5
  uint16_t FirmwareMajorVersion;
6
  uint16_t FirmwareMinorVersion;
7
  uint8_t AxCnt;
8
  uint32_t CpuClockRate;
9
  uint8_t CpuName[12];
10
  uint32_t FifoBufSize;
11
  uint8_t CompilationDate[22];
12
  uint8_t FirmwareName[11];
13
}TDeviceContext __attribute__((packed));

von AbcAbc (Gast)


Lesenswert?

Siehe Doku:
Attribut richtig anwenden
struct S { short f[3]; } _attribute_ ((packed));

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Aber ist natürlich auf einer 32-Bit-Maschine eine blöde Idee, die 
verschiedenen Elemente in so einer Form zu mischen. Irgendwer muss dann 
hingehen, und CpuClockRate aus ihren einzelnen Bytes zusammenpuzzeln, 
statt dass man einfach einen 32-bit-Wert aus dem Speicher liest.

von Geri (Gast)


Lesenswert?

Hallo zusammen

@Jörg W.

wenn ich das so mache, dann erhalte ich beim Compilieren folgende 
Warnung:

"../Controller/devinfo.h(383): warning: empty declaration"

und die sizeof liefert immer noch 70 Byte.


>Aber ist natürlich auf einer 32-Bit-Maschine eine blöde Idee, die
>verschiedenen Elemente in so einer Form zu mischen. Irgendwer muss dann
>hingehen, und CpuClockRate aus ihren einzelnen Bytes zusammenpuzzeln,
>statt dass man einfach einen 32-bit-Wert aus dem Speicher liest.
Die Datenstruktur wird nur einmal vom uC über USB ausgetauscht. Die 
Größe des USB-Datenpaketes beträgt 64 Byte. Die Struktur passt so halt 
genau rein...


@AbcAbc: bisher ließ sich sich der Code auf diese Weise unter gcc immer 
einwandfrei compilieren und funktionierte auch.

Beste Grüße

Geri

von Luther B. (luther-blissett)


Lesenswert?

AbcAbc schrieb:
> Siehe Doku:
> Attribut richtig anwenden
> struct S { short f[3]; } _attribute_ ((packed));

Zeit wieder einen Blick in die Doku zu werfen. gcc unterstützt #pragma 
pack() seit Version 4.0 - die kam 2005 raus. Ich glaube nicht, daß der 
Compiler vom OP so alt ist. Eventuell liegt das Problem doch woanders.

von Geri (Gast)


Lesenswert?

@Luther B. Hattest recht:)


Das Problem lag daran, dass ich das den Compiler-Direktive "GCC" 
vergessen hatte. Unter dieser Option wurden die Standard-Datentypen im 
Programm anders angelegt.
1
#ifdef TG_XP
2
  typedef unsigned __int16 uint16_t;
3
  typedef __int16 int16_t;
4
  typedef __int8 int8_t;
5
  typedef unsigned char uint8_t;
6
  typedef __int32 int32_t;
7
  typedef unsigned __int32 uint32_t;
8
  typedef unsigned __int64 uint64_t;
9
  typedef __int64 int64_t;
10
#elif GCC
11
  typedef unsigned short int uint16_t;
12
  typedef short int int16_t;
13
  typedef char int8_t;
14
  typedef unsigned char uint8_t;
15
  typedef int int32_t;
16
  typedef unsigned int uint32_t;
17
  typedef unsigned long long uint64_t;
18
  typedef long long int64_t;
19
#else
20
  typedef unsigned int uint16_t;
21
  typedef int int16_t;
22
  typedef int int8_t;
23
  typedef unsigned char uint8_t;
24
  typedef long int32_t;
25
  typedef unsigned long uint32_t;
26
  typedef unsigned long long uint64_t;
27
  typedef long long int64_t;
28
#endif

Nun klappt es. Vielen Dank nochmals

Geri

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Geri schrieb:
> Die Größe des USB-Datenpaketes beträgt 64 Byte. Die Struktur passt so
> halt genau rein...

Das kannst du auch ganz ohne "pack" haben, indem du die Felder passend 
sortierst:
1
typedef struct
2
{
3
  uint32_t CpuClockRate;
4
  uint32_t FifoBufSize;
5
  uint16_t HardwareMajorVersion;
6
  uint16_t HardwareMinorVersion;
7
  uint16_t FirmwareMajorVersion;
8
  uint16_t FirmwareMinorVersion;
9
  uint8_t CpuName[12];
10
  uint8_t CompilationDate[22];
11
  uint8_t FirmwareName[11];
12
  uint8_t AxCnt;
13
}
14
TDeviceContext

von A. S. (Gast)


Lesenswert?

Dein uint16_t ist (warum auch immer) 4 Byte groß.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Ist sowieso eine doofe Idee, diese Typen selbst zu definieren. Dafür 
nimmt man <stdint.h>.

Beitrag #5706930 wurde von einem Moderator gelöscht.
von Zweig (Gast)


Lesenswert?

Jörg W. schrieb:
> Ist sowieso eine doofe Idee, diese Typen selbst zu definieren. Dafür
> nimmt man <stdint.h>.

!!! ganz ganz genau. !!!

von Dirk B. (dirkb2)


Lesenswert?

Definiere int8_t als signed char, die 16 Bit Typen über short.

Bedenke auch, dass ein long auf 64-Bit Linux auch 64-Bit groß ist.

von Geri (Gast)


Lesenswert?

Vielen Dank für eure Tipps!

>Ist sowieso eine doofe Idee, diese Typen selbst zu definieren. Dafür
>nimmt man <stdint.h>.


Stimmt, ein Relikt aus alten Tagen. Habe nun umgestellt auf <stdint.h>. 
Hoffe, damit wird alles besser:)

Beste Grüße
Geri

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Siehe auch Serialisierung ... "packed" ist böse :-)

Geri schrieb:
> #elif GCC

Wenn schon dann "__GNUC__" - hilft aber auch nicht so wirklich, da der 
GCC auf verschiedenen Architekturen verschiedene Integer-Größen nutzt. 
stdint.h ist hier natürlich das richtige.

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.