Forum: Compiler & IDEs Struct per Pointerzugriff befüllen


von Ben Banane (Gast)


Lesenswert?

Hi, ich möchte in einem Struct alle Bits setzen. Es sollen also nachher 
alle uint8_t auf 255 und uint16_t auf 65535 stehen. Mehr Datentypen 
gibt's da auch nicht. Also keine Gefahr wegen Vorzeichen, etc.
Jetzt könnte ich die Variablen natürlich alle einzeln setzen. Ich muss 
aber Platz sparen. Leider ist memset auch zu groß. Deswegen habe ich 
folgendes geschrieben:

for (i = 0; i < sizeof(Data); i++) *(uint8_t *)(&Data+i) = 255;

Ist das korrekt so??? Die Größe wäre ok! Geht's "noch" schöner? Ist ein 
attiny.

von Peter II (Gast)


Lesenswert?

Ben Banane schrieb:
> Geht's "noch" schöner?

memset( &Data, 255, sizeof( sizeof(Data) );

von eagle user (Gast)


Lesenswert?

Ben Banane schrieb:

> Leider ist memset auch zu groß.

In dem Fall würde ich ein eigenes memset() bauen, also deine Schleife in 
eine Funktion packen -- rein zwecks der Schönheit. Als Bonus spart das 
auch Platz, sobald du es mehr als einmal brauchst.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Peter II schrieb:
> memset( &Data, 255, sizeof( sizeof(Data) );

Ein sizeof weniger.
1
struct irgendwas
2
{
3
  uint8_t etwas;
4
  uint8_t nochwas;
5
  uint16_t wasanderes;
6
  uint16_t nochwasanderes;
7
} Data;
8
9
memset(&Data, 255, sizeof (Data));

[edit]

memset soll zu groß sein?

Dann so:
1
struct irgendwas
2
{
3
  uint8_t etwas;
4
  uint8_t nochwas;
5
  uint16_t wasanderes;
6
  uint16_t nochwasanderes;
7
} Data;
8
9
uint16_t i;
10
11
for (i = 0; i < sizeof (Data); i++)
12
  ((uint8_t *) &Data)[i] = 255;

Das entspricht fast dem Vorschlag des Threadstarters, bis auf das 
Detail, daß der Index erst nach dem Typecast auf uint8_t* angewandt 
wird. Und das ist wichtig.

: Bearbeitet durch User
von Ben Banane (Gast)


Lesenswert?

Wie gesagt, memset scheidet aus.

Also ist meine Schleife so korrekt? Ich könnte mit der Größe leben, 
störe mich momentan eigentlich nur an der Operation "+i", die Zweifel 
weckt, ob es noch kleiner ginge.

von Torsten R. (Firma: Torrox.de) (torstenrobitzki)


Lesenswert?

Ben Banane schrieb:

> Also ist meine Schleife so korrekt?

Nein, Du solltest den nach uint8_t gecasteten Zeiger inkrementieren, 
nicht &Data
1
for ( i = 0; i < sizeof(Data); ++i ) 
2
    *( ( (uint8_t *)&Data ) + i) = 0xff;

mfg Torsten

: Bearbeitet durch User
von B. S. (bestucki)


Lesenswert?

Ben Banane schrieb:
> Ich könnte mit der Größe leben,
> störe mich momentan eigentlich nur an der Operation "+i", die Zweifel
> weckt, ob es noch kleiner ginge.

Schon mal geschaut, was der Compiler daraus macht?

Anderer Vorschlag:
1
uint8_t * Actual = (uint8_t *)&Data;
2
const uint8_t * const End = (const uint8_t *)(&Data + 1); // zeigt auf die erste Speicherstelle hinter Data
3
while(Actual != End){
4
  *Actual = 0xFF;
5
  Actual++;
6
}


Um zu prüfen, welche Variante weniger Speicher belegt, muss du das 
ASM-Listing anschauen. Rechne damit, dass es bei der nächsten 
Compilerversion wieder anders sein kann.

: Bearbeitet durch User
von Peter II (Gast)


Lesenswert?

Ben Banane schrieb:
> Wie gesagt, memset scheidet aus.

warum? hast du es mal gestestet (auch mit Optimierung)? Ich würde 
erwarten das der Compiler es inline als Schleife baut.

von Ben Banane (Gast)


Lesenswert?

Die (korrigierte) Schleife ist kleiner als memset und passt! 
Optimierungen sind natürlich an. Die Standardfunktionen sind halt nicht 
immer das Optimum.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Peter II schrieb:
> Ich würde erwarten das der Compiler es inline als Schleife baut.

Avr-gcc macht das bis dato (6.0) nur falls der Speicher gelöscht wird, 
d.h. wenn das 2. Argument 0 ist und falls die Anzahl der zu löschenden 
Bytes zur Compilezeit bekannt ist.

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.