mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Größe eines Strukturfeldes über Pointer ermitteln


Autor: Stephan Plaschke (steph0815)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So ich weiss jetzt gar nicht genau wie ich das beschreiben soll. Hoffe 
auch das mein Betr. überhaupt etwas aussagt. Mein Problem ist das ich 
ein Struktur habe welches so aussieht:
typedef struct{
  unsigned char length;
  unsigned char *cmd;
  void (*fct)(void);
} UART_MEN;
davon habe ich mehrere statisch angelegt:
static UART_MEN UART_menu_C[]={
    {3, "lr", UART_menu_flash_clr},
    {5, "lear", UART_menu_flash_clr}
};
...
Um diese jetzt zu verwalten habe ich ein Feld angelegt mit Pointern auf 
die einzelnen Strukturen
static UART_MEN *pUART_menu[]={
    UART_menu_C,
    ...
jetzt muss ich wissen wie lang mein Statisches Strukturenfeld ist.
Wenn ich
i=sizeof(UART_menu_C);
ausführe erhalte ich 12, was auch der Länge von 2 Strukturen entspricht. 
Da ich im Programm aber nur mit Pointern arbeite kann ich nur
i=sizeof(*pUART_menu_sub);
 verwenden.
Das gibt mir natürlich nur den Wert 6 da es ja nur auf die erste 
Struktur zeigt und nicht auf das gesammte Element.
Finde keine andere Art das zu machen, daher meine Frage ob das überhaupt 
so machbar ist oder ob es nicht machbar ist. Für jede Hilfe bin ich echt 
dankbar.
Kurze Erklärun noch dazu. Damit baue ich mir ein Menü auf welches über 
die UART gesteuert wird. Ich untersuche da den ersten Buchstaben, stimmt 
dieser den zweiten... dazu ist dann die Struktur da. In der wird die 
Länge des Befehls und der Befehl selber definiert. Jetzt muss ich aber 
wissen auf wie viele Elemente ich es für den jeweiligen ersten 
Buchstaben untersuchen muss.

Hoffe das iss nich zu verwirrend und mir kann jemand helfen.

Greetz
Stephan

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stephan Plaschke wrote:
> Das gibt mir natürlich nur den Wert 6 da es ja nur auf die erste
> Struktur zeigt und nicht auf das gesammte Element.
> Finde keine andere Art das zu machen, daher meine Frage ob das überhaupt
> so machbar ist oder ob es nicht machbar ist. Für jede Hilfe bin ich echt
> dankbar.

Ist nicht machbar.
Wenn du nur einen Pointer hast, der auf ein Array zeigt, ist es
nicht möglich, die Größe des Arrays zu bestimmen.

Genau das ist zb. die Krux bei allen String-verarbeitenden
Funktionen. Ein strcpy kann sich per Definition nicht davor
schützen, das Zielarray zu überschreiben, weil es aus dem erhaltenen
Pointer nicht die Größe des Arrays ermitteln kann.

-> Größe mit übergeben oder ein Dummy-Element ins Array einfügen,
welches die Rolle von 'ich bin das letzte' spielt.

> In der wird die Länge des Befehls und der Befehl selber
> definiert.

Diese Länge brauchst du wiederrum nicht. Diese Länge ist per
strlen aus dem Kommando bestimmbar.


In deinem Fall kannst du die Sache mit einer weiteren
Struktur retten, in der du einen Zeiger zu einem Menü
mit der Größe des Menüs verknüpfst.
static UART_MEN UART_menu_C[]={
    {3, "lr", UART_menu_flash_clr},
    {5, "lear", UART_menu_flash_clr}
};

static UART_MEN UART_menu_D[]={
    {3, "ar", UART_menu_flash_clr},
    {5, "beat", UART_menu_flash_clr}
};

struct Menus {
  UART_MEN* UART_menu;
  size_t    UART_menu_size;
}

#define ARRAY_SIZE(x) ( sizeof(x) / sizeof(*x) )

struct Menus UART_menu[] = {
   { UART_menu_C, ARRAY_SIZE( UART_menu_C ) },
   { UART_menu_D, ARRAY_SIZE( UART_menu_D ) }
};

Autor: OliverSo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Da ich im Programm aber nur mit Pointern arbeite kann ich 
nuri=sizeof>(*pUART_menu_sub);
>verwenden.

Und wer hindert dich daran, trotzdem
i=sizeof(UART_menu_C);
zu benutzen?

Oliver

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OliverSo wrote:
>>Da ich im Programm aber nur mit Pointern arbeite kann ich
> nuri=sizeof>(*pUART_menu_sub);
>>verwenden.
>
> Und wer hindert dich daran, trotzdem
i=sizeof(UART_menu_C);
> zu benutzen?
>

Dann setzt mal in diesem Code für die ??? richtig ein
static UART_MEN *pUART_menu[]={
    UART_menu_C,
    UART_menu_D,
    ...
}

void HandleMenu( UART_MENU* pMenu )
{
  // male alle Einträge des Menüs

  for( i = 0; i < sizeof( ???? ); ++i )
    ...
}

int main()
{
  int i = 0;

  ...

  HandleMenu( pUART_menu[i] );
}

Autor: Stephan Plaschke (steph0815)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Karl heinz Buchegger
Dachte ich mir. Werd das mit einer weiteren Struktur lösen. Vielen Dank!

@
OliverSo
Mein Programm! Ich habe ja nur einen Buchstaben und der zeigt über einen 
Pointer auf das erste Element des Feldes. Da ich aber nicht immer mit 
if() oder ähnlichen abfragen will welchen Buchstaben ich habe ist es 
nicht möglich immer direkt abzufragen.

Danke noch mal!!

Steph0815

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger wrote:
>
> #define ARRAY_SIZE(x) ( sizeof(x) / sizeof(*x) )
> 
> struct Menus UART_menu[] = {
>    { UART_menu_C, ARRAY_SIZE( UART_menu_C ) },
>    { UART_menu_D, ARRAY_SIZE( UART_menu_D ) }
> };
> 

Dies liese sich mit einem weiteren Makro noch ein bischen
einfacher und weniger fehleranfällig machen
#define ARRAY_SIZE(x) ( sizeof(x) / sizeof(*x) )
#define UART_ENTRY(x) x, ARRAY_SIZE(x)

struct Menus UART_menu[] = {
   { UART_ENTRY( UART_menu_C ) },
   { UART_ENTRY( UART_menu_D ) }
};

Am Prinzip ändert sich aber nichts. Ein 'Menus' Eintrag enthält
einen Pointer zum Menü-Array sowie dessen Größe.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stephan Plaschke wrote:
> Mein Programm! Ich habe ja nur einen Buchstaben und der zeigt über einen
> Pointer auf das erste Element des Feldes. Da ich aber nicht immer mit
> if() oder ähnlichen abfragen will welchen Buchstaben ich habe ist es
> nicht möglich immer direkt abzufragen.

Üder diese Abfrage sollte man sowieso noch mal reden.
Anstatt da mit Buchstaben rumzuwurschteln, warum benutzt
du nicht einfach einen strcmp()?

http://www.mikrocontroller.net/articles/FAQ#strcmp...

String wird komplett von der UART geholt und danach das Menü
Eintrag für Eintrag durchgegangen und mittels strcmp() verglichen
ob eines der Kommandos übereinstimmt. Wenn ja, wird die
zugehörige Funktion aufgerufen. Fertig!
int EvaluateCommand( struct Menus* pSubMenu, const char* cmd )
{
  for( size_t i = 0; i < pSubMenu->UART_menu_size; ++i ) {
    if( strcmp( pSubMenu->UART_menu[i].cmd, cmd ) == 0 ) {
      if( pSubMenu->UART_menu[i].fct != NULL )
        (*(pSubMenu->UART_menu[i].fct))();
      return 1;
    }
  }

  return 0;
}

Autor: Stephan Plaschke (steph0815)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger wrote:
> Stephan Plaschke wrote:
>> Mein Programm! Ich habe ja nur einen Buchstaben und der zeigt über einen
>> Pointer auf das erste Element des Feldes. Da ich aber nicht immer mit
>> if() oder ähnlichen abfragen will welchen Buchstaben ich habe ist es
>> nicht möglich immer direkt abzufragen.
>
> Üder diese Abfrage sollte man sowieso noch mal reden.
> Anstatt da mit Buchstaben rumzuwurschteln, warum benutzt
> du nicht einfach einen strcmp()?


Da hast du wirklch recht. Habe das jetzt auch so geändert. Ich suche 
immer noch nach den ersten Buchstaben, ist dieser üngültig exit. Danach 
nehme ich dann aber nicht strcmp() sondern strcasecmp() ist ja 
eigentlich das gleiche nur unterscheidet Groß- und Kleinbuchstaben. Ist 
dann ein gültiger Befehl erkannt ausführen des Befehls wenn nicht 
Abbruch mit Error. Ganz einfach wenn ich das so betrachte!

Vielen Dank Karl heinz Buchegger, viel Arbeit erspart!!

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.