Forum: PC-Programmierung [C] Struktur ist zu groß


von struct (Gast)


Lesenswert?

Ich habe mir in C eine Struktur erstellt, sie ist aber zu groß. Mein 
Testcode
1
typedef struct __attribute__((__packed__))
2
{
3
  uint16_t A;  //    2
4
  uint32_t B;  // +  4
5
  uint16_t C;  // +  2
6
  uint16_t D;  // +  2
7
  uint32_t E;  // +  4
8
}F;            // = 14 
9
10
int main(int argc, char **argv)
11
{
12
  printf("%d", sizeof(F));
13
  return 0;
14
}
gibt 16 aus, ich kommen aber nur auf 14 bytes. Woher kommt das?

Ja ich weiß, es gibt padding Bytes, sollte ich diese mit
1
__attribute__((__packed__))
aber nicht ausschalten? Oder muss man sie noch mehr ausschalten um eine 
14 Byte große Struktur zu erhalten?

von Pfeiffer (Gast)


Lesenswert?

__attribute__((packed, aligned(...)))

von (prx) A. K. (prx)


Lesenswert?

gcc 4.7.2 x86-64: 14
gcc 4.8.1 ARM:    14
gcc 4.7.2 AVR:    14

von Daniel A. (daniel-a)


Lesenswert?

Welcher Compiler?

Mit offsetof kannst du herausfinden, woher die zusätzlichen bytes 
kommen.

von struct (Gast)


Lesenswert?

Pfeiffer schrieb:
> __attribute__((packed, aligned(...)))
Hat leider nichts gebracht

Daniel A. schrieb:
> Welcher Compiler?
GCC in Code::Blocks. Wieso ist der wichtig, sieht der C-Standard da 
nichts vor?
> Mit offsetof kannst du herausfinden, woher die zusätzlichen bytes
> kommen.
B hat Offset 4, A ist also zu groß.

von Rolf M. (rmagnus)


Lesenswert?

struct schrieb:
> Ja ich weiß, es gibt padding Bytes, sollte ich diese
> mit__attribute__((_packed_))aber nicht ausschalten?

Beim GCC ja. Da passiert das bei mir auch.

struct schrieb:
> GCC in Code::Blocks. Wieso ist der wichtig, sieht der C-Standard da
> nichts vor?

Nein. Es gibt ja auch genug Hardware-Plattformen, die das nicht vorsehen 
und beim Versuch, auf sowas zuzugreifen, eine CPU-Exception auslösen.

>> Mit offsetof kannst du herausfinden, woher die zusätzlichen bytes
>> kommen.
> B hat Offset 4, A ist also zu groß.

Dann wird wohl das Attribut aus irgendeinem Grund ignoriert.

von struct (Gast)


Lesenswert?

Hat keiner eine Idee wie ich die Struktur auf 14 Byte reduzieren kann, 
oder bleibt nur der Ausweg über ein uint8_t array[14]; und ein paar 
Pointer-Casts?

von struct (Gast)


Lesenswert?

Oder, eigentlich hätte ich auf Frühere darauf kommen können, die 
Struct-Member einzeln aus der Datei lesen, anstatt der Gesamten Struktur 
in einem Mal.

Wie man Padding wirklich ausschalten kann würde ich für die Zukunft 
trotzdem gerne wissen.

von Daniel H. (Firma: keine) (commander)


Lesenswert?

struct schrieb:
> Hat keiner eine Idee wie ich die Struktur auf 14 Byte reduzieren kann,
> oder bleibt nur der Ausweg über ein uint8_t array[14]; und ein paar
> Pointer-Casts?

Du könntest noch versuchen die Elemente anders anzuordnen:
1
typedef struct __attribute__((__packed__))
2
{
3
  uint32_t B;  // +  4
4
  uint32_t E;  // +  4
5
  uint16_t A;  //    2
6
  uint16_t C;  // +  2
7
  uint16_t D;  // +  2
8
}F;            // = 14

Es könnte sein dass dein Compiler versucht das Ganze auf 32-bit zu 
alignen und daher das erste uint16 um zwei Bytes padded.

von Konrad S. (maybee)


Lesenswert?

Mach A zum letzten Element in der Struktur.

von TestX (Gast)


Lesenswert?

gibt es denn irgendeinen funktionalen/technischen grund was dich an dem 
padding stört ?
es wird mit sicherheit ein problem mit deinem compiler/makefile sein, 
dass das passiert. generell hat es aber einen grund wieso die strukturen 
durch den compiler erweitert werden. daher sollte man sich da eher nicht 
drum kümmern

von (prx) A. K. (prx)


Lesenswert?

Daniel H. schrieb:
> Es könnte sein dass dein Compiler versucht das Ganze auf 32-bit zu
> alignen und daher das erste uint16 um zwei Bytes padded.

Wenn er packed ignoriert, dann wird er in deiner Version hinten 2 Bytes 
ranhängen.

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

Es gibt in GCC eine Warnung -Wpadded.

von Mark B. (markbrandis)


Lesenswert?

struct schrieb:
> Wie man Padding wirklich ausschalten kann würde ich für die Zukunft
> trotzdem gerne wissen.

Ernst gemeinte Frage: Warum?

Du hast im Forum PC-Programmierung gepostet. Ich bezweifle, dass es in 
real existierender PC-Software relevante Probleme wegen des Paddings 
gibt.

Wo es kein Problem gibt, sollte man nicht seine Zeit damit verschwenden 
es lösen zu wollen.

Etwas anderes wäre es natürlich bei einem kleinen Mikrocontroller mit 
sehr wenig Speicher.

: Bearbeitet durch User
von struct (Gast)


Lesenswert?

Daniel H. schrieb:
> Du könntest noch versuchen die Elemente anders anzuordnen
Konrad S. schrieb:
> Mach A zum letzten Element in der Struktur.
Geht leider nicht.

TestX schrieb:
> gibt es denn irgendeinen funktionalen/technischen grund was dich an dem
> padding stört ?
Ja, ich würde gerne einen Fileheader mit
1
F G;
2
fread(&G, sizeof(F), 1, file);
auslesen.

von Alabama J. (alabamajack)


Lesenswert?

struct schrieb:
> Daniel H. schrieb:
>> Du könntest noch versuchen die Elemente anders anzuordnen
> Konrad S. schrieb:
>> Mach A zum letzten Element in der Struktur.
> Geht leider nicht.

warum sollte das nicht gehen?? . Wie

TestX schrieb:
> gibt es denn irgendeinen funktionalen/technischen grund was dich
> an dem
> padding stört ?
> es wird mit sicherheit ein problem mit deinem compiler/makefile sein,
> dass das passiert. generell hat es aber einen grund wieso die strukturen
> durch den compiler erweitert werden. daher sollte man sich da eher nicht
> drum kümmern

schon geschrieben hat, padded dein compiler. Warum auch immer, das kann 
dir hier keiner weissagen...

von Daniel A. (daniel-a)


Lesenswert?

Mark B. schrieb:
> Du hast im Forum PC-Programmierung gepostet. Ich bezweifle, dass es in
> real existierender PC-Software relevante Probleme wegen des Paddings
> gibt.

Natürlich gibt es die. Wenn man z.B. eine Binärdatei einlesen oder 
Abspeichern möchte, sind diese gepackten struckts wirklich nützlich. Ich 
denke es ist wichtig dieses Verhalten zu Räproduzieren, möglicherweise 
ist es ja ein ernstzunehmender bug in gcc. Welche GCC Version wird 
eigentlich verwendet?

von Georg (Gast)


Lesenswert?

Mark B. schrieb:
> Ich bezweifle, dass es in
> real existierender PC-Software relevante Probleme wegen des Paddings
> gibt.

Zu kurz gedacht: in jedem Fall gibt es Probleme, wenn die Struktur auch 
woanders verwendet wird, z.B. in einer DLL, oder Bestandteil einer 
Dateidefinition ist und eben 14 Byte gross. Nicht jeder Programmierer 
lebt nur einsam in seiner eigenen Welt und muss sich wie du um nichts 
kümmern.

Und wenn du meinst das wäre selten: fast jede Windows-Funktion ist 
begleitet von einer Definition der Struktur zur Datenübergabe, und die 
kann man ja nicht einfach so ignorieren - nicht wenn das Programm auch 
funktionieren soll.

Georg

von __f__ (Gast)


Lesenswert?

Daniel A. schrieb:
> Mark B. schrieb:
>> Du hast im Forum PC-Programmierung gepostet. Ich bezweifle, dass es in
>> real existierender PC-Software relevante Probleme wegen des Paddings
>> gibt.
>
> Natürlich gibt es die. Wenn man z.B. eine Binärdatei einlesen oder
> Abspeichern möchte, sind diese gepackten struckts wirklich nützlich. Ich
> denke es ist wichtig dieses Verhalten zu Räproduzieren, möglicherweise
> ist es ja ein ernstzunehmender bug in gcc. Welche GCC Version wird
> eigentlich verwendet?

genau man sollte es unbedingt "räproduzieren"...

Schon mal was von Wahrscheinlichkeiten gehört? Die die immer als erstes 
nach Bugs im gcc/ sonstigen Compiler schreien sind die, die den größten 
Stuss-C schreiben

von Programmierer (Gast)


Lesenswert?

struct schrieb:
> Ja, ich würde gerne einen Fileheader mit F G;
> fread(&G, sizeof(F), 1, file);
> auslesen.

Da garantiert der C Standard sowieso kein definiertes Verhalten. Daher 
macht das unpassende Padding auch nichts schlimmer. Die einzig korrekte 
Lösung mit definiertem Verhalten besteht darin, Bytes in ein char Array 
zu lesen, und dann mit Bitshifts und so zu den gewünschten Datentypen 
zusammenzubauen. Der GCC kann das weitgehend optimieren.

von Konrad S. (maybee)


Lesenswert?

struct schrieb:
> Ja, ich würde gerne einen Fileheader mit
> ...
> auslesen.

Typischer Anfängerfehler beim Design der Struktur. ;-)
Erst die großen, dann kleiner werdend. Hier also erst alle 32-Bit-Typen, 
dann alle 16-Bit-Typen. Sowas vermeidet Ärger von Anfang an.

von Oliver R. (Gast)


Lesenswert?

Falls das Problem unter Windows/MINGW auftritt, versuche es mal mit der 
Compiler Option -mno-ms-bitfields

von struct (Gast)


Lesenswert?

Alabama J. schrieb:
> warum sollte das nicht gehen?? . Wie
Hast du meinen Post zu Ende gelesen?

Daniel A. schrieb:
> Natürlich gibt es die. Wenn man z.B. eine Binärdatei einlesen oder
> Abspeichern möchte, sind diese gepackten struckts wirklich nützlich.
Genau

Programmierer schrieb:
> Die einzig korrekte
> Lösung mit definiertem Verhalten besteht darin, Bytes in ein char Array
> zu lesen
Was wäre damit?
1
F G;
2
fread(&G.A, sizeof(G.A), 1, file);
3
fread(&G.B, sizeof(G.B), 1, file);
4
fread(&G.C, sizeof(G.C), 1, file);
5
// usw.

Konrad S. schrieb:
> Typischer Anfängerfehler beim Design der Struktur. ;-)
Ich glaube kaum, dass die Bitmap von Anfängern erfunden wurde.

Oliver R. schrieb:
> -mno-ms-bitfields
Hat leider nichts gebracht

von Mark B. (markbrandis)


Lesenswert?

Daniel A. schrieb:
> Mark B. schrieb:
>> Du hast im Forum PC-Programmierung gepostet. Ich bezweifle, dass es in
>> real existierender PC-Software relevante Probleme wegen des Paddings
>> gibt.
>
> Natürlich gibt es die. Wenn man z.B. eine Binärdatei einlesen oder
> Abspeichern möchte

Ich lese Bytes immer mit unsigned char ein, respektive uint8_t. :-)

von Daniel A. (daniel-a)


Lesenswert?

Programmierer schrieb:
> struct schrieb:
>> Ja, ich würde gerne einen Fileheader mit F G;
>> fread(&G, sizeof(F), 1, file);
>> auslesen.
>
> Da garantiert der C Standard sowieso kein definiertes Verhalten. Daher
> macht das unpassende Padding auch nichts schlimmer

Doch, dass tut er.
1
size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );

Das erste Argument ist ein void pointer, also gibt es keine Probleme mit 
aliasing rule oder änlichem, und der zweite Parameter ist extra dafür 
gemacht die grösse des Datentyps anzugeben. Der C Standard stellt 
sicher, dass der Speicher des Struckts überschrieben wird. Er stellt 
auch sicher, dass die struct member die richtige reihenfolge haben und 
der erste member offset 0 hat. Das packet ist zwar nicht teil des C 
Standards, aber gcc, msvcc, keil, und viele andere Compiler garantieren, 
dass dieses das Padding entfernt. Wenn er sich noch manuell um die 
Endianess kümmert, hat er alles richtig gemacht und es muss 
funktionieren. ( ausser er hätte ein #define _attribute_ oder ein 
#define _packed_ im code, aber dass ist doch sehr unwahrscheinlich. )

Diese nutzung von fread ist genauso üblich wie das nullen von Structs 
mit memset.

von Mark B. (markbrandis)


Lesenswert?

struct schrieb:
> Ich glaube kaum, dass die Bitmap von Anfängern erfunden wurde.

Bitmaps einlesen oder in Dateien schreiben macht man nun wirklich seit 
vielen Jahren so, dass man passende Bibliotheken dafür verwendet. 
Niemand muss dafür erst mal selbst eine Struktur definieren.

Unter C zum Beispiel ginge das mit der Library von ImageMagick.

Allgemeiner (falls es keine der üblichen, bekannten Bitmaps ist):
Wenn diese Datenstruktur jemand anders definiert hat, dann wird 
derjenige doch wohl hoffentlich auch Funktionen zum Ein- und Auslesen 
dafür geschrieben haben. Denn wie sonst würde er seinen eigenen 
Abstrakten Datentyp verwenden?

Womit wir wieder beim üblichen Problem auf mikrocontroller.net sind:
Es wurde nicht die eigentliche Aufgabe beschrieben, sondern ein 
(womöglich falscher oder unnötig komplizierter) Lösungsansatz.

: Bearbeitet durch User
von Konrad S. (maybee)


Lesenswert?

Und PLOPP, schon ist eine Bitmap aus dem Hut gezaubert, womöglich 
nochdazu irgendein Standard, der aber noch nicht verraten werden soll, 
gell? ;-

von struct (Gast)


Lesenswert?

Konrad S. schrieb:
> womöglich
> nochdazu irgendein Standard, der aber noch nicht verraten werden soll,
> gell? ;-
Ich weiß zwar nicht was das damit zu tun haben soll, dass der Compiler 
meine Strukturen nicht packen will aber es geht darum:
https://en.wikipedia.org/wiki/BMP_file_format#Bitmap_file_header

von Konrad S. (maybee)


Lesenswert?

Nimm sowas (war bei mir der erste Google-Treffer für "bmp library"):
http://easybmp.sourceforge.net/

Ansonsten: Doch, ja, das waren irgendwie schon Anfänger. Zur 
Entstehungszeit von BMP war MSDOS und Windows noch 16-Bit-Software. Da 
haben die noch keinen Bedarf für Alignment jenseits von 16 Bit gesehen.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Wenn es um ein Programm für x86* geht, ist das Alignment aber kein Thema 
- die Architektur unterstützt beliebiges (Mis)alignment. Wird zwar etwas 
langsamer, ein um ein Byte verschobener 32-Bit-Zugriff, aber er 
funktioniert.

Deswegen ist es sehr merkwürdig, daß der Compiler hier sich nicht 
erwartungsgemäß verhält.


*) Das ist zumindest naheliegend, ist das hier doch der Forenbereich 
"PC-Programmierung".

von struct (Gast)


Lesenswert?

struct schrieb:
> Was wäre damit?F G;
> fread(&G.A, sizeof(G.A), 1, file);
> //usw.
Mir fällt gerade auf, dass ich damit noch Probleme mit der Endianness 
hätte. Also bleibt wirklich nur noch das uint8_t Array. Wär zu schön 
gewesen wenn ich die Struktur in einem einlesen gekonnt hätte :-(

Konrad S. schrieb:
> Nimm sowas
Man braucht doch keine Lib nur um ein paar Pixel aus einer Datei zu 
lesen und zudem ist die Lib C++.

Rufus Τ. F. schrieb:
> *) Das ist zumindest naheliegend, ist das hier doch der Forenbereich
> "PC-Programmierung".
Core-i7

von Mark B. (markbrandis)


Lesenswert?

struct schrieb:
> Konrad S. schrieb:
>> womöglich
>> nochdazu irgendein Standard, der aber noch nicht verraten werden soll,
>> gell? ;-
> Ich weiß zwar nicht was das damit zu tun haben soll, dass der Compiler
> meine Strukturen nicht packen will aber es geht darum:
> https://en.wikipedia.org/wiki/BMP_file_format#Bitmap_file_header

Wie gesagt. Dafür gibt es Bibliotheken. Man muss das Rad nicht neu 
erfinden.


struct schrieb:
> Konrad S. schrieb:
>> Nimm sowas
> Man braucht doch keine Lib nur um ein paar Pixel aus einer Datei zu
> lesen

Man braucht auch kein Flugzeug um bis nach Barcelona zu kommen. Zu Fuß 
dauert es aber nun mal erheblich länger.

: Bearbeitet durch User
von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

struct schrieb:
> Core-i7

Welches Betriebssystem? Und Code für x86 oder x64?

von struct (Gast)


Lesenswert?

Rufus Τ. F. schrieb:
> Welches Betriebssystem? Und Code für x86 oder x64?
Windows 8.1 64bit

von Bernd K. (prof7bit)


Lesenswert?

struct schrieb:
> Wär zu schön
> gewesen wenn ich die Struktur in einem einlesen gekonnt hätte :-(

Wenn der Architekt dieser Struktur mitgedacht hätte dann hätte er die 
Daten von vorneherein in der Reihenfolge genau so angeordnet daß jedes 
Element an einem Vielfachen seiner eigenen Länge zu liegen kommt. Schau 
Dir zum Beispiel mal TCP-Header oder ähnliche Strukturen an die noch aus 
der alten Zeit[TM] stammten, jener glorreichen alten Zeit in der 
Software noch richtige Software, Protokolle noch richtige Protokolle und 
Programmierer noch richtige Programmierer waren.

von (prx) A. K. (prx)


Lesenswert?

Bernd K. schrieb:
> Wenn der Architekt dieser Struktur mitgedacht hätte

Diesen Satz kann man sich bei PCs einrahmen und an die Wand hängen. Die 
Historie von Hard- und Software ist geprägt vom Denken bis zum nächsten 
Laternenpfahl und keinen Meter darüber hinaus. Angefangen mit dem 
Prozessor über die Boardhardware und das BIOS bis hin zu den 
Betriebssystemen.

: Bearbeitet durch User
von Konrad S. (maybee)


Lesenswert?

struct schrieb:
> Man braucht doch keine Lib nur um ein paar Pixel aus einer Datei zu
> lesen und zudem ist die Lib C++.

Wie gesagt: Das war der erste Treffer bei Google, da gab es noch ein 
paar hundert Treffer mehr. Such dir was aus. Oder kümmere dich ggf. 
selbst um Endianess usw. Zu Fuß nach Barcelona hat auch seinen Reiz, du 
lernst Land und Leute kennen. ;-)

Bernd K. schrieb:
> von vorneherein in der Reihenfolge genau so angeordnet daß jedes
> Element an einem Vielfachen seiner eigenen Länge zu liegen kommt.

Tja, wenn's wie bei BMP die "richtigen" Leute machen, dann sind es keine 
Anfänger sondern Standard-Setzer. ;-)

von struct (Gast)


Lesenswert?

Konrad S. schrieb:
> Wie gesagt: Das war der erste Treffer bei Google
Ich weiß, ich hab schon aus deinen vorigen Posts gesehen, dass du dir 
überhaupt keine Mühe gibst mir zu Helfen.

von Mark B. (markbrandis)


Lesenswert?

struct schrieb:
> Konrad S. schrieb:
>> Wie gesagt: Das war der erste Treffer bei Google
> Ich weiß, ich hab schon aus deinen vorigen Posts gesehen, dass du dir
> überhaupt keine Mühe gibst mir zu Helfen.

Weißt du was? Deine Einstellung kotzt mich an. Jeder, der dir hier 
hilft, verschwendet seine Zeit!

: Bearbeitet durch User
von Ulli (Gast)


Lesenswert?

Versuchs mal damit:
1
#pragma pack(push,1)
2
typedef struct
3
{
4
  uint16_t A;  //    2
5
  uint32_t B;  // +  4
6
  uint16_t C;  // +  2
7
  uint16_t D;  // +  2
8
  uint32_t E;  // +  4
9
}F;            // = 14
10
#pragma pack(pop)

von struct (Gast)


Lesenswert?

Mark B. schrieb:
> Weißt du was? Deine Einstellung kotzt mich an
Dann verschwinde doch, du hast hier eh nichts zu meiner Frage 
beigetragen.
> Jeder, der dir hier hilft, verschwendet seine Zeit!
Nicht jeder. Eine Frage, die nicht gestellt wurde, zu beantworten ist 
natürlich verschwendete Zeit. Wenn jemand einen Teller Nudel bestellt 
ist es auch verschwendete Zeit ihm ein Stake zu Grillen.

Ulli schrieb:
> Versuchs mal damit:
Vielen Dank, das war's :-)

Weiters geht noch Dank an alle anderen die versucht haben meine Frage zu 
beantworten.

PS Das Thema kann geschlossen werden.

von struct (Gast)


Lesenswert?

PPS Was ich aus diesem Thread noch gelernt habe, ist das ich in Zukunft 
mit Infos sparsamer sein werde. Um das Padding zu entfernen ist genau 0 
(in Worten Null) Wissen nötig wozu die Struktur verwendet wird und 
wenn's nicht geht, ein uint8 Array in die struktur schreiben kann ich 
auch alleine.

von Mikro 7. (mikro77)


Lesenswert?

Eine Compiler- und Architekturunabhängige Implementierung ist häufig 
vorzuziehen. Hier bspw.
1
#include <stdint.h>
2
3
struct Header
4
{
5
  uint8_t id[2] ; // we support only ASCII 'B','M'
6
  uint32_t fsize ; // file size
7
  uint16_t r1 ; // reserved (0)
8
  uint16_t r2 ; // reserrvd (0)
9
  uint32_t poffset ; // offset to actual pixel array
10
  uint32_t dsize ; // DIB header size, either 40, 108 (v4) or 124 (v5) 
11
} ;
12
13
static uint16_t lsbf16(uint8_t const data[2])
14
{
15
  uint16_t dst = data[1] ;
16
  dst <<= 8 ; dst |= data[0] ;
17
  return dst ;
18
}
19
20
static uint32_t lsbf32(uint8_t const data[4])
21
{
22
  uint32_t dst = data[3] ;
23
  dst <<= 8 ; dst |= data[2] ;
24
  dst <<= 8 ; dst |= data[1] ;
25
  dst <<= 8 ; dst |= data[0] ;
26
  return dst ;
27
}
28
29
struct Header import(uint8_t const data[18])
30
{
31
  struct Header header ;
32
  header.id[0] =           data[ 0] ;
33
  header.id[1] =           data[ 1] ;
34
  header.fsize =   lsbf32(&data[ 2]) ;
35
  header.r1 =      lsbf16(&data[ 6]) ;
36
  header.r2 =      lsbf16(&data[ 8]) ;
37
  header.poffset = lsbf32(&data[10]) ;
38
  header.dsize =   lsbf32(&data[14]) ;
39
  return header ;
40
}

von Daniel A. (daniel-a)


Lesenswert?

Ich habe gerade eine Library geschrieben, die aus ein par Macros 
structdefinitionen und eine Parser Funktion generiert, die auchnoch die 
Endianess berücksichtigt. Falls es jemand brauchen kann, hier:
https://github.com/Daniel-Abrecht/RWTransform

von c-hater (Gast)


Lesenswert?

Mark B. schrieb:

> Ernst gemeinte Frage: Warum?
>
> Du hast im Forum PC-Programmierung gepostet. Ich bezweifle, dass es in
> real existierender PC-Software relevante Probleme wegen des Paddings
> gibt.

Dann hast du absolut keine Ahnung. Es gibt z.B. unzählige Dateiformate, 
die gepackte Strukturen enthalten. Und wenn man diese sinnvoll lesen 
oder schreiben möchte, dann stellt sich das Problem natürlich.

Natürlich kann man Workarounds für dieses Problem finden, die ohne 
gepackte Strukturen auskommen. Aber diese werden erstens weniger 
effizient und zweitens weniger gut lesbar sein.

von Flo (Gast)


Lesenswert?

Es geht auch mit dem "attribute". Muss nur hinter die Strukturdefinition 
bzw sogar hinter die definierte Variable. Bin grad nicht ganz sicher. 
Aber dann klappt das auch. Schon etliche Male so gemacht.
Auch wenn es Alles schon irgendwie als Bibliothek gibt, solange man das 
für sich privat macht mach ruhig weiter so. Kann man nur was bei lernen.

Gruß
Flo

von Tcf K. (tcfkao)


Lesenswert?

Daniel A. schrieb:
> Ich habe gerade eine Library geschrieben, die aus ein par Macros
> structdefinitionen und eine Parser Funktion generiert, die auchnoch die
> Endianess berücksichtigt.

Hallo Daniel,
finde ich toll dass Du mal so "on the fly" eine Library schreibst. Ein 
paar Fragen habe ich, weil ich selber auch dazulernen will:
1
void rw_fixEndianes( void* mem, size_t size, size_t count, enum rw_endianess e ){
2
  if( endianess != e ){
3
    char* start = mem;
4
    char* end   = start + size*count + 1 - size;
5
    for( char* it=start; it<end; it += size )
6
      for( size_t i=0; i<size/2; i++ ){
7
        char tmp = it[i];
8
        it[i] = it[size-i-1];
9
        it[size-i-1] = tmp;
10
      }
11
  }
12
}

- Kann man in C im Kopf der for-Schleife Variablen deklarieren? Ich 
dachte, das ginge nur in C++
- Wird die Variable tmp innerhalb der innersten for-Schleife nicht bei 
jedem Aufruf neu auf dem Stack erzeugt? Wäre eine Deklaration innerhalb 
des if-Blockes nicht laufzeitgünstiger? Oder optimiert das der Compiler?

Danke im Voraus!

von Ulli (Gast)


Lesenswert?

> - Kann man in C im Kopf der for-Schleife Variablen deklarieren? Ich
> dachte, das ginge nur in C++
Ab irgendeinem C-Standard, weiß jetzt nich auswendig welchem, ist das 
möglich.

von Rolf M. (rmagnus)


Lesenswert?

Ulli schrieb:
>> - Kann man in C im Kopf der for-Schleife Variablen deklarieren? Ich
>> dachte, das ginge nur in C++
> Ab irgendeinem C-Standard, weiß jetzt nich auswendig welchem, ist das
> möglich.

Das ist seit C99 so, also erst seit 16 Jahren. Kann natürich nicht jeder 
in so kurzer Zeit mitkriegen. ;-)

von Tcf K. (tcfkao)


Lesenswert?

Genau, ich programmiere noch in K&R, Zeilenlänge nicht über 72 wegen der 
Lochkarten... ;)

von Daniel A. (daniel-a)


Lesenswert?

Tcf K. schrieb:
> - Kann man in C im Kopf der for-Schleife Variablen deklarieren? Ich
> dachte, das ginge nur in C++

Ja, das geht ab C99. Es werden von der lib noch anonyme unions 
verwendet, die ab C11 oder alternativ als GNU/Keil/MSVCC extension 
verfügbar sind.

> - Wird die Variable tmp innerhalb der innersten for-Schleife nicht bei
> jedem Aufruf neu auf dem Stack erzeugt? Wäre eine Deklaration innerhalb
> des if-Blockes nicht laufzeitgünstiger? Oder optimiert das der Compiler?

Wenn der Compiler dass auf den stack legt ist dafür eigentlich immer 
ein pop und ein push erforderlich, unabhängig davon, ob die Variable 
vorher oder nachher auf dem stack gelegt wurde. Praktisch sind Compiler 
da aber recht kreativ, und es würde mich sehr Überraschen wenn diese 
kein freies Register für die 3 Variablen finden, oder nicht sogar eine 
davon wegoptimieren würden. Überprüft habe ich das aber nicht.

Es gab hier mal einen Thread, der sich mit sowas änlichem beschäftigte, 
ich werde den mal suchen.

von Mark B. (markbrandis)


Lesenswert?

struct schrieb:
> Mark B. schrieb:
>> Weißt du was? Deine Einstellung kotzt mich an
> Dann verschwinde doch, du hast hier eh nichts zu meiner Frage
> beigetragen.
>> Jeder, der dir hier hilft, verschwendet seine Zeit!
> Nicht jeder. Eine Frage, die nicht gestellt wurde, zu beantworten ist
> natürlich verschwendete Zeit.

Falsch. Wir haben hier andauernd Themenersteller, die mit fragwürdigen 
Lösungsansätzen ankommen. Selbstverständlich muss man in solchen Fällen 
den Ansatz hinterfragen.

Es gilt immer der Grundsatz:
Beschreibe nicht den Lösungsansatz, sondern beschreibe das zu lösende 
Problem. Jeder, der Ahnung von Software-Entwicklung hat, wird Dir das 
bestätigen.

struct schrieb:
> PPS Was ich aus diesem Thread noch gelernt habe, ist das ich in Zukunft
> mit Infos sparsamer sein werde. Um das Padding zu entfernen ist genau 0
> (in Worten Null) Wissen nötig wozu die Struktur verwendet wird und
> wenn's nicht geht, ein uint8 Array in die struktur schreiben kann ich
> auch alleine.

Dann hast Du leider nichts dazugelernt. Schade drum.

von Mark B. (markbrandis)


Lesenswert?

c-hater schrieb:
> Mark B. schrieb:
>
>> Ernst gemeinte Frage: Warum?
>>
>> Du hast im Forum PC-Programmierung gepostet. Ich bezweifle, dass es in
>> real existierender PC-Software relevante Probleme wegen des Paddings
>> gibt.
>
> Dann hast du absolut keine Ahnung. Es gibt z.B. unzählige Dateiformate,
> die gepackte Strukturen enthalten. Und wenn man diese sinnvoll lesen
> oder schreiben möchte, dann stellt sich das Problem natürlich.

Das Problem stellt sich in diesem Fall überhaupt gar nicht, weil das 
Einlesen und Ausgeben von .bmp Dateien ein längst gelöstes Problem ist.

Kein vernünftiger Entwickler schreibt für eine solche Aufgabe eigenen 
Code. In aller Regel würde er damit nur Zeit vergeuden, und zu 99% eine 
schlechtere Lösung fabrizieren als jene die bereits existieren.

: Bearbeitet durch User
von struct (Gast)


Lesenswert?

Mark B. schrieb:
> Dann hast Du leider nichts dazugelernt. Schade drum.
Falsch, und wie ich was gelernt habe. Die ganzen besserwissenden Idioten 
halt ich mir vom Leib wenn ich keine Details poste.

Mark B. schrieb:
> Kein vernünftiger Entwickler schreibt für eine solche Aufgabe eigenen
> Code.
Hat Arduino dass man vom Einsatz fertiger Libs eher verblödet als was 
lernt nicht schon zur Genüge gezeigt?

von Daniel A. (daniel-a)


Lesenswert?

Daniel A. schrieb:
>> - Wird die Variable tmp innerhalb der innersten for-Schleife nicht bei
>> jedem Aufruf neu auf dem Stack erzeugt?
> Es gab hier mal einen Thread, der sich mit sowas änlichem beschäftigte,
> ich werde den mal suchen.

Gefunden: Beitrag "Unterschied zwischen int i; in while und vor while"

von Mark B. (markbrandis)


Lesenswert?

struct schrieb:
> Mark B. schrieb:
>> Dann hast Du leider nichts dazugelernt. Schade drum.
> Falsch, und wie ich was gelernt habe. Die ganzen besserwissenden Idioten
> halt ich mir vom Leib wenn ich keine Details poste.

Hurra! Jemand der auf dem "ich hab nichts verstanden" Status 
stehenbleiben will. Ja, solche Leute braucht das Forum. :-(

von Mark B. (markbrandis)


Angehängte Dateien:

Lesenswert?

Im Übrigen kann man eine Bitmap-Datei auch einlesen, ohne überhaupt 
irgendeine Struktur zu verwenden. Der angehängte Beispielcode sucht nach 
IDAT Tags und gibt deren Byte-Position innerhalb der Datei aus. (war 
eine Lösung für eine Aufgabe auf einer Challenge Website)

Ja ich weiß, selbst Code geschrieben :-)
Das ist aber viele Jahre her und damals wusste ich es nicht besser. 
Heute würde ich das selbstverständlich anders machen.

: Bearbeitet durch User
von Rolf M. (rmagnus)


Lesenswert?

struct schrieb:
> Mark B. schrieb:
>> Dann hast Du leider nichts dazugelernt. Schade drum.
> Falsch, und wie ich was gelernt habe. Die ganzen besserwissenden Idioten
> halt ich mir vom Leib wenn ich keine Details poste.

Dann hast du leider das falsche gelernt. Die Erfahrung zeigt, daß man 
die besten Antworten bekommt, wenn man sein Problem vollständig 
beschreibt, während bei Geheimniskrämern erst ellenlange Diskussionen 
ohne brauchbare Antworten kommen, da die Antwortenden mangels 
Beschreibung die Frage nicht verstehen und die Antworten daher in die 
falsche Richtung gehen. Das sieht man doch hier im Thread sehr gut. 
Einer der ersten Vorschläge war, die Elemente umzusortieren, so daß sich 
das Alignment-Problem gar nicht erst ergibt. Hättest du gleich gesagt, 
wofür du das brauchst, hätte man sich die Antwort sparen können.

von Bernd K. (prof7bit)


Lesenswert?

Tcf K. schrieb:
> - Wird die Variable tmp innerhalb der innersten for-Schleife nicht bei
> jedem Aufruf neu auf dem Stack erzeugt? Wäre eine Deklaration innerhalb
> des if-Blockes nicht laufzeitgünstiger? Oder optimiert das der Compiler?

Nein, das wirkt sich nur rein formell auf die Sichtbarkeit der Variablen 
aus, nach dem Schließen der geschweiften Klammer der Schleife ist die 
Variable einfach nicht mehr sichtbar/benutzbar, Der Compiler jedoch 
(weil er sich erstmal den Überblick verschafft wenn er das übersetzt) 
lässt dann von vorneherein Platz für soviele verschiedene lokalen 
Variablen wie er jemals gleichzeitig brauchen wird genau einmal beim 
Eintritt in die Funktion reservieren und lässt das erst beim return 
wieder aufräumen.

Natürlich kann der Compiler den reservierten Platz für diese Variable im 
weiteren Verlauf der Funktion nochmal für was anderes verwenden (weil 
der Platz eh schon reserviert ist), er kann den selben Platz auf dem 
Stack viele male wiederverwenden, reservieren muss er ihn jedoch nur 
einmal beim Eintritt und freigeben nur einmal beim Verlassen.

von (prx) A. K. (prx)


Lesenswert?

Bernd K. schrieb:
> Der Compiler jedoch
> (weil er sich erstmal den Überblick verschafft wenn er das übersetzt)
> lässt dann von vorneherein Platz für soviele verschiedene lokalen
> Variablen

Mit Optimierung übersetzt landen die ohnehin vorrangig in Registern, 
sofern der Code das zulässt. Auch da kann das gleiche Register für 
verschiedene Variablen verwendet werden. Wobei ein guter Compiler dafür 
nicht die Sichtbarkeit als Grundlage nimmt, sondern eigene Analysen der 
Verwendung.

Oft wird deshalb überhaupt kein Platz auf dem Stack benötigt, oder nur 
für push/pop von Registern, was ebenfalls summarisch an Anfang und Ende 
der Funktion geschieht.

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

struct schrieb:
> Falsch, und wie ich was gelernt habe. Die ganzen besserwissenden Idioten
> halt ich mir vom Leib wenn ich keine Details poste.

Noch weitaus effektiver wäre es, wenn du diese Strategie im Beitrag von 
vorneherein bekannt gibst. Erst das hätte die unpassende Antworten 
erspart.

von Mark B. (markbrandis)


Lesenswert?

Rolf M. schrieb:
> struct schrieb:
>> Mark B. schrieb:
>>> Dann hast Du leider nichts dazugelernt. Schade drum.
>> Falsch, und wie ich was gelernt habe. Die ganzen besserwissenden Idioten
>> halt ich mir vom Leib wenn ich keine Details poste.
>
> Dann hast du leider das falsche gelernt. Die Erfahrung zeigt, daß man
> die besten Antworten bekommt, wenn man sein Problem _vollständig_
> beschreibt, während bei Geheimniskrämern erst ellenlange Diskussionen
> ohne brauchbare Antworten kommen, da die Antwortenden mangels
> Beschreibung die Frage nicht verstehen und die Antworten daher in die
> falsche Richtung gehen. Das sieht man doch hier im Thread sehr gut.
> Einer der ersten Vorschläge war, die Elemente umzusortieren, so daß sich
> das Alignment-Problem gar nicht erst ergibt. Hättest du gleich gesagt,
> wofür du das brauchst, hätte man sich die Antwort sparen können.

Endlich mal einer, der es verstanden hat. Vielen Dank Rolf.

von (prx) A. K. (prx)


Lesenswert?

Mark B. schrieb:
> Endlich mal einer, der es verstanden hat. Vielen Dank Rolf.

Das haben ziemlich viele verstanden. Einige freilich stänkern rum, wenn 
sie nicht gleich die perfekte Antwort auf ihre doch so klar gestellte 
Frage kriegen.

Und dabei nicht einmal Betriebssystem, Compiler-Typ und -Version nennen, 
obwohl genau das hierfür essenziell war. Mit compilerspezifischem 
GCC-Code einen Compiler zu bewerfen, der Microsoft-Code haben will, 
bringt eben nichts. Ulli hatte zufällig die einzige noch betriebsfähige 
Glaskugel.

Deshalb ja auch meine Bitte an "struct", potentielle Antworter bitte 
gleich in der Frage zu Idioten zu erklären. Das vereinfacht es für beide 
Seiten erheblich.

: Bearbeitet durch User
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.