Forum: Compiler & IDEs Datenzuweisung an Struct


von Sven (Gast)


Lesenswert?

Hallo,

ich kann meinen ATmega32 mit dem AVR-GCC einigermassen gut 
Programmieren, bin aber auf eine Sache gestossen die ich nicht lösen 
kann. Habe versucht darüber Informationen zu finden, allerdings ohne 
Erfolg.

Mein Problem ist folgendes:

Ich habe einen Struct definiert und möchte gerne "numerisch" auf die 
jeweiligen Elemente zugreifen.

Der Struct:

struct zeitformat
  {
  uint8_t sekunden;
  uint8_t minuten;
  uint8_t stunden;
  } aktuellezeit;

Jetzt lese ich die RTC aus und weise aktuellezeit.sekunden die Sekunden 
zu, das selbe mache ich mit den Minuten und Stunden. Dies funktioniert 
auch alles, nur muss ich für jedes Element des Struct's eine Zuweisung 
schreiben (viel Programmcode). Einfacher wäre eine Schleife - geht das ?

Gibt es eine Möglichkeit auf die Elemente des Sruct's auch mit einer 
Variablen zuzugreifen?

Vielen Dank für einen Tip

von Nex (Gast)


Lesenswert?

Oder mit nem Pointer darauf zugreifen

von Eugen (Gast)


Lesenswert?

soetwas hab ich mal benutzt um beim initialisieren ein struct zu löschen 
(als ich noch nicht wusste wie es anders geht).

dabei musste ich erst die Pointeradresse des structs in ein u_int casten 
(zum zählen, sonst zählt er dabei bei (&STRUKTUR)+i das i als vielfache 
von sizeof(STRUKTUR) )
und dann diesen neuen u_int als charpointer casten um auf einzelne Bytes 
schreiben zu können

//löschen des structs
for(unsigned int i =0;i<sizeof(STRUKTUR);i++)
{
      *(unsigned char*)((unsigned int)(&STRUKTUR)+i)=0;
}

in deinem Fall würde ich aber aufpassen, denn sobald du verschiedengroße 
Datentypen in deinem struct hast, musst du sowieso für jede Variable dir 
überlegen wie groß die Variable ist und was da rein muss.
ein Feld von void* (wegen den verschiedenen Datentypen) würde dir 
vieleicht helfen. dann könntest du zum einem auf die Werte per Zeiger 
iterativ zugreifen und zum anderen ihnen per defines Namen geben.

von Karl H. (kbuchegg)


Lesenswert?

> Jetzt lese ich die RTC aus und weise aktuellezeit.sekunden die
> Sekunden zu, das selbe mache ich mit den Minuten und Stunden. Dies
> funktioniert auch alles, nur muss ich für jedes Element des
> Struct's eine Zuweisung schreiben (viel Programmcode).

Das wirst du nicht einfacher machen können. Sind doch nur 3.
1
  aktuellezeit.sekunden = sekunden_vom_rtc;
2
  aktuellezeit.minuten  = minuten_vom_rtc;
3
  aktuellezeit.stunden  = stunden_vom_rtc;

Allenfals könnte man sich noch eine Funktion dafür schreiben:
1
void AssignTime( struct zeitformat* zeit,
2
                 uint8_t stunden, uint8_t minuten, uint8_t sekunden )
3
{
4
  zeit->sekunden = sekunden;
5
  zeit->minuten  = minuten;
6
  zeit->studnen  = stunden;
7
}

und die dann benutzen, wenn so eine Zuweisung häufiger auftritt
1
    ...
2
    AssignTime( &aktuellezeit, stunden_vom_rtc, minuten_vom_rtc, sekunden_vom_rtc );
3
    ....
4
    ....
5
    AssignTime( &aktuellezeit, stunden_vom_rtc, minuten_vom_rtc, sekunden_vom_rtc );

Falls du Zeiten aneinander zuweisen musst, dann kannst du das mit
einer normalen Zuweisung machen
1
   struct zeitformat a;
2
   struct zeitformat b;
3
4
   ...
5
   AssignTime( &a, stund, minut, sekund );
6
   ...
7
   b = a;

Wenn du die Zeit auf 0 setzen musst, kannst du alternativ
1
  AssignTime( &a, 0, 0, 0 );
oder
1
  memset( &a, 0, sizeof( a ) );
benutzen.

von Rup (Gast)


Lesenswert?

Die Strukturzuweisung nach ANSI C99 lautet:
1
struct zeitformat a;
2
3
a = { .sekunden = x, .minuten = y, .stunden = z };

Das sollte jeder moderner GNU-Compiler ab 3.0 können.
Man kann sich auch leicht ein Makro daraus bauen:
1
#define MAKE_ZEITFORMAT(stu, min, sek) (struct zeitformat){.sekunden = sek, .minuten = min, stunden = .stu}

von holger (Gast)


Lesenswert?

>Ich habe einen Struct definiert und möchte gerne "numerisch" auf die
>jeweiligen Elemente zugreifen.

Wozu definierst du dann ein struct? Nimmst halt ein Array.

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


Lesenswert?

Rup wrote:

> Die Strukturzuweisung nach ANSI C99 lautet:

Es gibt kein “ANSI C99”.  Es gibt nur ein “ISO/IEC 9899:1999”, kurz
“ISO C99”.

> a = { .sekunden = x, .minuten = y, .stunden = z };

Das ist keine Zuweisung, sondern eine Initialisierung und auch
nur in diesem Kontext zulässig.

von Martin L. (melvin_the_moose)


Lesenswert?

1
struct zeitformat
2
  {
3
  uint8_t sekunden;
4
  uint8_t minuten;
5
  uint8_t stunden;
6
  };
7
8
typedef struct zeitformat zeitformat_t;
9
10
union zeit_union
11
  {
12
  zeitformat_t s;
13
  uint8_t b[3];
14
  } aktuellezeit;
15
16
  /*Zuweisung durch Strukturelement*/
17
  aktuellezeit.s.sekunden = 12u;
18
  aktuellezeit.s.minuten  = 34u;
19
  aktuellezeit.s.stunden  = 11u;
20
21
  /*Zuweisen in einer Schleife*/
22
  for (unsigned int i=0; i<3; i++)
23
  {
24
  aktuellezeit.b[i]=0;
25
  }

Ich habe das Beispiel nicht compiliert. Ich hoffe, es sind keine 
Syntaxfehler drin...
Aber so müßte es gehen, wenn es sein muß. Empfehlenswert ist diese Art 
des Zugriffs auf Strukturelemente jedoch nicht, da der Compiler je nach 
Elementtypen im struct Lücken im Speicherlayout einfügen kann. Ein 
bestimmter Arrayindex entspricht dann nicht immer einem bestimmten 
Strukturelement. Dieses Verhalten ist (Compiler-) 
implementierungsabhängig und möglicherweise nicht portabel.

von Also nee (Gast)


Lesenswert?

Man könnte auch ein Array definieren und den Inidzes vorher per Makros 
Namen geben:
1
typedef uint8_t zeitformat[3];
2
3
#define SEKUNDEN 0
4
#define MINUTEN 1
5
#define STUNDEN 2
6
7
aktuellezeit[SEKUNDEN] = 12;
8
aktuellezeit[MINUTEN] = 34;
9
aktuellezeit[STUNDEN] = 11;
10
11
for (unsigned int i=0; i<3; i++)
12
{
13
   aktuellezeit[i]=0;
14
}

So kann man auf union-Hacks verzichten.

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.