Forum: Compiler & IDEs Anzahl der Felder eines struct array


von struct (Gast)


Lesenswert?

Ich habe mir eine struct folgendermaßen definiert:
1
typedef struct {
2
   uint16_t id;
3
   uint16_t mask;
4
   char msg[8];
5
   void (*fp)(void);
6
} CAN_MSG_T;
und eine array davon angelegt
1
const CAN_MSG_T message[] = {
2
   { 0x39C , 0x7FF , "\0" , can_rec_mob0 },
3
   { 0x66E , 0x7FF , "\0" , can_rec_mob1 },
4
   { 0x30B , 0x7FF , "\0" , can_rec_mob2 }
5
}
Meine Frage ist nun, woher ich weiß wie groß das Array der Strukt ist??

Kann ich da mit sizeof arbeiten, oder optimiert der Compiler da noch 
dran rum bzw. fügt Leerräume ein, welche das Ergebnis verfälschen 
würden?

Ich hatte an sowas gedacht:
1
for( i = 0; i < sizeof( message ); ++i )
2
    ...
3
}

von der mechatroniker (Gast)


Lesenswert?

sizeof(message) / sizeof(message[0])

ist dein Freund.

von struct (Gast)


Lesenswert?

THX, aber ich habe mal gelesen, dass der Compiler unter Umständen 
Leerräume zwischen den einzelnen Elementen einfügt. Das würde das 
Ergebnis ja dann verfälschen oder sehe ich da was falsch?

von Karl H. (kbuchegg)


Lesenswert?

struct schrieb:
> THX, aber ich habe mal gelesen, dass der Compiler unter Umständen
> Leerräume zwischen den einzelnen Elementen einfügt.

Innerhalb eines structs ist das schon möglich.

> Das würde das
> Ergebnis ja dann verfälschen oder sehe ich da was falsch?

Du siehst das falsch. Falls es da irgendwelche Restriktionen gibt, die 
der Compiler einhalten muss, dann muss er das erledigen, indem er das 
einzelne Array-Element aufbläst. Zwischen 2 Array-Elementen an sich kann 
keine Lücke sein, die nicht durch Vergrößerung der sizeof eines 
einzelnen Array-Elements entsteht. Ansonsten würde die komplette 
Array-Indizierung, die über Pointerarithmetik definiert ist (die 
wiederrum auf sizeof beruht) sofort zusammenbrechen.

von Harri Hirsch (Gast)


Lesenswert?

struct schrieb:

> THX, aber ich habe mal gelesen, dass der Compiler unter Umständen
> Leerräume zwischen den einzelnen Elementen einfügt.

Dann hat da entweder jemand ziemlichen Mist geschrieben, oder du 
verwechselst es mit Struktur-Elementen. Array-Elemente liegen immer 
direkt hintereinander.

von Karl H. (kbuchegg)


Lesenswert?

Darf man fragen, wozu das hier
1
"\0"
gut sein soll?

Der Compiler schliesst jeden String automatisch mit einem \0 Zeichen ab. 
(OK, eine Ausnahme gibt es. Die trifft hier aber nicht zu)

von struct (Gast)


Lesenswert?

OK seh ich ein.
Da hab ich gleich noch mal eine Frage. Ich habe mir nun eine Funktion 
erstellt, welche die Variable message übergeben bekommt. Also,
1
void funktionsname (CAN_MSG_T *canmsg){
2
  for (uint8_t mob=0; mob<(sizeof(canmsg)/sizeof(canmsg[0])); mob++ ){
3
    canmsg[mob].mask = ...;
4
    ...
5
  }
6
}

Ist das so richtig, oder muss es heißen canmsg[mob]->mask wegen dem 
pointer?

von Karl H. (kbuchegg)


Lesenswert?

struct schrieb:
> OK seh ich ein.
> Da hab ich gleich noch mal eine Frage. Ich habe mir nun eine Funktion
> erstellt, welche die Variable message übergeben bekommt. Also,
>
>
1
> void funktionsname (CAN_MSG_T *canmsg){
2
>   for (uint8_t mob=0; mob<(sizeof(canmsg)/sizeof(canmsg[0])); mob++ ){
3
>     canmsg[mob].mask = ...;
4
>     ...
5
>   }
6
> }
7
>
>
> Ist das so richtig

Nein. Hier ist das falsch.
An dieser Stelle kannst du die Größe des Arrays nicht mehr feststellen.

Die Funktion bekommt nicht das Array übergeben, sondern einen Pointer 
auf den Anfang des Arrays. Aus dem Pointer ist aber nicht mehr ablesbar 
ob
* er überhaupt auf ein Array zeigt
* und wenn ja, wieviele Arrayelemente da vorhanden sind.


Du musst die Arraygröße mitgeben

Wenn du dir da unsicher bist, dann spiel einfach Compiler (denn sizeof 
wird vom Compiler bereits zu einem Zahlenwert ausgewertet)

Wenn du nur das gegeben hast

  void funktionsname (CAN_MSG_T *canmsg){

und zusätzlich auch noch weißt wie groß ein CAN_MSG_T ist, kannst du dir 
dann ausrechnen wie groß 'das übergebene Array' ist? Konkret. In Form 
von Zahlen. Nicht als Formel. Schaffst du es, nur durch betrachten 
dieser einen Zeule mit einem Zahlenwert dafür hochzukommen?

Du kannst es nicht, weil dir Informationen fehlen. Und genausowenig kann 
es der Compiler.

von Rolf Magnus (Gast)


Lesenswert?

struct schrieb:
> void funktionsname (CAN_MSG_T *canmsg){
>   for (uint8_t mob=0; mob<(sizeof(canmsg)/sizeof(canmsg[0])); mob++ ){

Das geht so nicht. Du hast von einem Array gesprochen, nicht von einem 
Zeiger. sizeof(canmsg)/sizeof(canmsg[0]) wird dir Unsinn zurückgeben, 
weil du die Größe eines Zeigers durch die Größe einer CAN_MSG_T teils.

>     canmsg[mob].mask = ...;
>     ...
>   }
> }
>
> Ist das so richtig, oder muss es heißen canmsg[mob]->mask wegen dem
> pointer?

Der Punkt ist schon richtig. Der Index-Operator sorgt schon für die 
Dereferenzierung.

von struct (Gast)


Lesenswert?

OK danke. Ich habs jetzt wieder als normale globale Variable. Da brauch 
ich der Funktion gar nicht mehr übergeben^^

von Karl H. (kbuchegg)


Lesenswert?

struct schrieb:
> OK danke. Ich habs jetzt wieder als normale globale Variable. Da brauch
> ich der Funktion gar nicht mehr übergeben^^

Feigling.
So wirst du Parameterübergabe nie lernen, wenn du immer gleich auf 
globale Variablen ausweichst.

von struct (Gast)


Lesenswert?

Naja, ich hab das schon verstanden, was ihr mir gesagt habt mit der 
Größe. Es ist aber auch so, dass die struct nur ein einziges mal 
existiert und sowieso global sein muss, da auch eine isr drauf zugreift.

von Karl H. (kbuchegg)


Lesenswert?

struct schrieb:
> Naja, ich hab das schon verstanden, was ihr mir gesagt habt mit der
> Größe.

Gut

> Es ist aber auch so, dass die struct nur ein einziges mal
> existiert und sowieso global sein muss, da auch eine isr
> drauf zugreift.

Das hat damit gar nicht mal soviel zu tun. Es ist nur so, dass 
Funktionen universeller verwendbar werden, wenn sie von keinen globalen 
Variablen abhängen. OK, das wird jetzt bei dir nicht die große Rolle 
spielen, von daher ist es ok. Es hat nur so geklungen, als ob du da den 
Weg des geringsten Widerstands gehst :-)

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.