Forum: Mikrocontroller und Digitale Elektronik Zeiger und Unterprogramm


von Siegfried S. (dieleena)


Lesenswert?

Hallo,
Während der Laufzeit werden die Adresse verschiedene Unterprogramme in 
einem Array gespeichert.

nur als Beispiel
ram unsigned int   *FifoZeiger;
FifoZeiger  = (unsigned int*)(void*)&TESTEN1;
list[0].call = FifoZeiger;
FifoZeiger  = (unsigned int*)(void*)&TESTEN2;
list[1].call = FifoZeiger;

Danach möchte ich über die im Array gespeicherte Adresse auf das 
Unterprogramm zugreifen.

so wollte ich es ausführen
list[1].call();

bekomme aber dieses Fehlermeldung.
call of non-function

The operand of the '()' function call post-fix operator must be of type
'pointer to function.' Most commonly, this is a function identifier.
Common causes include missing scope parentheses.


Gruß Siegfried

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Wie ist die Struktur definiert, von der Du ein Array namens "list" 
angelegt hast? Hier ist insbesondere das Strukturelement "call" 
interessant.

von Karl H. (kbuchegg)


Lesenswert?

Siegfried Saueressig schrieb:
> Hallo,
> Während der Laufzeit werden die Adresse verschiedene Unterprogramme in
> einem Array gespeichert.
>
> nur als Beispiel
> ram unsigned int   *FifoZeiger;
> FifoZeiger  = (unsigned int*)(void*)&TESTEN1;

Autsch.

Du bist auf der Suche nach Funtkionszeigern.

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

von Siegfried S. (dieleena)


Lesenswert?

hallo,

typedef struct
  {
    unsigned char aktiv;     // High ist aktiv
    signed int time;         // Zeit
    unsigned int  *call;     // Task
  } task;

Gruß Siegfried

von Karl H. (kbuchegg)


Lesenswert?

>   unsigned int  *call;     // Task

Njet. Das Stichwort lautet 'Funktionspointer'

von Klaus W. (mfgkw)


Lesenswert?

Wenn die Funktion eine unsigned int als Rückgabewert liefert und
keine Parameter hat, dann so deklarieren:
1
 unsigned int (*call)(void);

von Siegfried S. (dieleena)


Lesenswert?

hallo,
jetzt habe ich es. nochmals ganz klein angefangen

unsigned int list[5];
typedef void (*call)( void );
call my_call[5];

void TESTEN1()    //(void)
  {list[0]= 33;}

void TESTEN2()    //(void)
  {list[1] = 55;}

void list_call(void)
{
list[0] = 0;
list[1] = 0;
list[2] = 0;
list[3] = 0;
list[4] = 0;

my_call[0] = TESTEN1;      //FifoZeiger;
my_call[1] = TESTEN2;      //FifoZeiger;

 my_call[0]();
 my_call[1]();
}

vielen dank an alle
Gruß Siegfried

von Siegfried S. (dieleena)


Lesenswert?

hallo,
nun bin ich ein Schritt weiter.
typedef void (*typedef_call)( void );

typedef struct
  {
    unsigned char aktiv;     // if true: ready to run
    signed int time;       // desired wakeup time
    typedef_call my_call;
  } struct_task;

struct_task tasklist[5] ;
unsigned int list[5];

void TESTEN1()    //(void)
  {
list[0]= 33;
  }
void TESTEN2()    //(void)
  {
list[1] = 55;
  }

void run_task(void)
  {
tasklist[0].my_call = TESTEN1;
tasklist[1].my_call = TESTEN2;

tasklist[0].my_call();
tasklist[1].my_call();
  }


wie kann ich die Funktionzeiger direkt im Array verangern, ohne das ich 
es im Code hochladen muß?



Gruß Siegfried

von Karl H. (kbuchegg)


Lesenswert?

Siegfried Saueressig schrieb:

> wie kann ich die Funktionzeiger direkt im Array verangern, ohne das ich
> es im Code hochladen muß?

Nochmal. Und diesmal bitte in einem deutschen Satz.

von gast (Gast)


Lesenswert?

mal ganz einfach :

[/pseudocode]

typedef void (*typedef_call)( void );
typedef_call buffer[10];

in_den_buffer( typedef_call   funktion )
{
  buffer[i] = funktion ;
}

void task(void)
{
  typedef_call   funktion;

  funktion = buffer[i];
  buffer[i] = NULL ;
  funktion();

}

aufruf :

in_den_buffer( TESTEN1) ;


in der main
while(1)
  task();




da fehlen jez noch einige while oder für und die abfragen
und sicherheiten ...
ber vom prinzip her geht das so
auch ganz easy abzuändern mit parametern

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Ich vermute, daß er das Array initialisieren will.

Das sollte so gehen:

struct_task tasklist[] = { { 0, 0, TESTEN1 }, { 0, 0, TESTEN2 } };

Es ist übrigens eine ganz schlechte Idee, Funktionsnamen komplett in 
Versalien zu schreiben. Die Konvention sieht vor, daß dadurch 
Präprozessordefinitionen gekennzeichnet werden.

von Siegfried S. (dieleena)


Lesenswert?

hallo,
ups...
war keine gute Beschreibung von mir.
habe von @Rufus t. Firefly übernommen.

@Rufus t. Firefly
kannst du mir das erklären, bzw eine alternative beschreiben? Habe es 
nie gelernt.
Es ist übrigens eine ganz schlechte Idee, Funktionsnamen komplett in
Versalien zu schreiben. Die Konvention sieht vor, daß dadurch
Präprozessordefinitionen gekennzeichnet werden.

Gruß Siegfried

von Karl H. (kbuchegg)


Lesenswert?

Ist ganz einfach:

Die weltweit übliche Konvention lautet:
Namen, die komplett in Grossbuchstaben geschrieben sind, sind für Makros 
reserviert.

Damit weiß jeder Programmierer weltweit, dass es sich bei
1
  ...
2
3
  x = MAX( a, b );

bei MAX um ein Makro handelt. Und da er weiß, wie dieses Makro 
üblicherweise implementiert wird, wird er ums verrecken das nicht 
schreiben ...
1
   ...
2
3
   x = MAX( a++, b-- );

... weil je nach konkreten Zahlenwerten a sich auch um 2 erhöhen kann 
(oder b um 2 verringern).

sieht er dagegen, diesen Code
1
   ...
2
3
   x = max( a, b );

dann geht er davon aus, dass es sich um eine echte Funktion handelt und 
bei Bedarf kann er dann auch schreiben
1
   x = max( a++, b-- );

und alles wird so funktionieren, wie man sich das erwartet.

Wie gesagt: Es handelt sich nur um eine Konvention. Aber es ist eine die 
Sinn macht und an die sich alle halten. Es gibt keinen Grund, diese 
Konvention leichtfertig als Einzelner über Bord zu werfen.

von Siegfried S. (dieleena)


Lesenswert?

hallo,
habe folgendes geschrieben. Funktioniert.

t_task tasklist[] =
{
//  aktiv,   time,  call                   ID
{  1,   0,   toggle_led_status   },   0
{  0,   0,  beeper     },   1
{  0,   0,  transfer_service  },   2
{  0,   0,  find_service  },   3
{  0,   0,  transfer_bus  },   4
{  1,   0,  find_bus    },   5
{  0,   0,  prozess_del  },   6
{  0,   0,  prozess_add  },   7
{  0,   0,  prozess_run  }    8
};

Wie finde ich heraus, welcher ID z.B.  -> prozess_del <-  hat?

Gruß Siegfried

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Meinst Du mit "ID" den Index im Array?

von Siegfried S. (dieleena)


Lesenswert?

@Rufus t. Firefly
ja.
es geht mir darum, das ich in verschiedene Routinen per Name auf die 
Einträge von -> prozess_del <- zugreifen kann.

möchte nicht innerhalb meines Projekt so zugreifen
-> tasklist[6].aktiv = 0; <- . Sollte ich die Reihenfolge in der Liste 
ändern, müßte ich das ganze Projekt durchforsten zum ändern des Index.

Gruß Siegfried

von Karl H. (kbuchegg)


Lesenswert?

Siegfried Saueressig schrieb:
> hallo,
> habe folgendes geschrieben. Funktioniert.
>
> t_task tasklist[] =
> {
> //  aktiv,   time,  call                   ID
> {  1,   0,   toggle_led_status   },   0
> {  0,   0,  beeper     },   1
> {  0,   0,  transfer_service  },   2
> {  0,   0,  find_service  },   3
> {  0,   0,  transfer_bus  },   4
> {  1,   0,  find_bus    },   5
> {  0,   0,  prozess_del  },   6
> {  0,   0,  prozess_add  },   7
> {  0,   0,  prozess_run  }    8
> };
>
> Wie finde ich heraus, welcher ID z.B.  -> prozess_del <-  hat?

Ist das jetzt eine Fangfrage?

Du gehst das Array in einer Schleife durch, und wenn du auf einen 
Eintrag stösst, dessen Funktionspointer identisch ist mit der 
Startadresse von prozess_del, dann lieferst du den Index an dem du 
fündig wurdest. Eine stinknormale Suchschleife, wie sie jeden Tag von 
mindestens 3 Millionen C-Programmiereren geschrieben wird.

1
int searchId( typedef_call function )
2
{
3
  int i;
4
5
  for( i = 0; i < sizeof( tasklist ) / sizeof(tasklist[0]); ++i )
6
    if( function == tasklist[i].my_call )
7
      return i;
8
9
  return -1;
10
}
11
12
int main()
13
{
14
  ...
15
16
  id = searchId( prozess_del );
17
18
  ...


PS: Was dir wahrscheinlich fehlt, ist die Erkentnis, dass der Name einer 
Funktion (also ohne die (), welche einen Aufruf der Funktion 
kennzeichnen ) ganz einfach für die Adresse der Funktion steht. So wie 
der Name eines Arrays ohne die [] für die Startadresse des Arrays steht.

von Phantomix X. (phantomix)


Lesenswert?

> möchte nicht innerhalb meines Projekt so zugreifen
> -> tasklist[6].aktiv = 0; <- . Sollte ich die Reihenfolge in
> der Liste ändern, müßte ich das ganze Projekt durchforsten
> zum ändern des Index.


Wie wärs mit einem define?

1
#define PROZESS_DEL prozess_del
2
#define PROZESS_DEL_ID 6
3
4
{  0,   0,  PROZESS_DEL  },   PROZESS_DEL_ID

Dann verwendest du überall im Code nur noch PROZESS_DEL_ID und brauchst 
die nur noch an einer Stelle ändern.

von Siegfried S. (dieleena)


Lesenswert?

@Phantomix Ximotnahp


Beispiel erzeugt "task.c:147:Error: syntax error"

t_task tasklist[] =
{
//  aktiv,   time,  call
{  1,  0,   TOGGLE_LED_STATUS   },   TOGGLE_LED_STATUS_ID
{  0,  0,  BEEPER     },  BEEPER_ID
{  0,  0,  TRANSFER_SERVICE  },   TRANSFER_SERVICE_ID
{  0,  0,  FIND_SERVICE  },   FIND_SERVICE_ID
{  0,  0,  TRANSFER_BUS  },   TRANSFER_BUS_ID
{  1,  0,  FIND_BUS    },   FIND_BUS_ID
{  0,  0,  PROZESS_DEL  },   PROZESS_DEL_ID
{  0,  0,  PROZESS_ADD  },  PROZESS_ADD_ID
{  0,  0,  PROZESS_RUN  }   PROZESS_RUN_ID
};

Gruß Siegfried

von Phantomix X. (phantomix)


Lesenswert?

Du hast die defines dazu vergessen. Außerdem ein komma vor 
PROZESS_RUN_ID

Versuchs mal so
1
#define TOGGLE_LED_STATUS_ID 0
2
#define BEEPER_ID 1
3
#define TRANSFER_SERVICE_ID 2
4
#define FIND_SERVICE_ID 3
5
#define TRANSFER_BUS_ID 4
6
#define FIND_BUS_ID 5
7
#define PROZESS_DEL_ID 6
8
#define PROZESS_ADD_ID 7
9
#define PROZESS_RUN_ID 8
10
11
t_task tasklist[] =
12
{
13
//  aktiv,   time,  call
14
  {  1,  0,   toggle_led_status   },   TOGGLE_LED_STATUS_ID
15
  {  0,  0,  beeper     },  BEEPER_ID
16
  {  0,  0,  transfer_service  },   TRANSFER_SERVICE_ID
17
  {  0,  0,  find_service  },   FIND_SERVICE_ID
18
  {  0,  0,  transfer_bus  },   TRANSFER_BUS_ID
19
  {  1,  0,  find_bus    },   FIND_BUS_ID
20
  {  0,  0,  prozess_del  },   PROZESS_DEL_ID
21
  {  0,  0,  prozess_add  },  PROZESS_ADD_ID
22
  {  0,  0,  prozess_run  }   PROZESS_RUN_ID
23
};

von Karl H. (kbuchegg)


Lesenswert?

Siegfried Saueressig schrieb:
> @Phantomix Ximotnahp
>
>
> Beispiel erzeugt "task.c:147:Error: syntax error"

Das kommt daher, dass du immer nur irgendwelche Codefetzen postest und 
wir hier raten müssen, wie deine Datenstrukturen aussehen.
Auch wäre es vernünftig, wenn du selbst compilierbaren Code posten 
könntest, denn schon deine Vorgabe
1
t_task tasklist[] =
2
{
3
//  aktiv,   time,  call                   ID
4
{  1,   0,   toggle_led_status   },   0
5
{  0,   0,  beeper     },   1
6
{  0,   0,  transfer_service  },   2
7
{  0,   0,  find_service  },   3
8
{  0,   0,  transfer_bus  },   4
9
{  1,   0,  find_bus    },   5
10
{  0,   0,  prozess_del  },   6
11
{  0,   0,  prozess_add  },   7
12
{  0,   0,  prozess_run  }    8
13
};

kann ziemlich offensichtlich nicht stimmen, oder was sollen die Zahlen 
am jeweils rechten Rand jeder Zeile?

von Phantomix X. (phantomix)


Lesenswert?

kam mir auch schon spanisch vor. ist das C2009? bin wohl zu lang mit 
Java beschäftigt gewesen

von Karl H. (kbuchegg)


Lesenswert?

Phantomix Ximotnahp schrieb:
> Du hast die defines dazu vergessen. Außerdem ein komma vor
> PROZESS_RUN_ID
>
> Versuchs mal so

Vergiss es.
Seine Datenstruktur sieht ganz anders aus als du denkst.

von Siegfried S. (dieleena)


Lesenswert?

@Phantomix Ximotnahp

>>  Du hast die defines dazu vergessen.
nein, habe ich nur nicht gepostet.

>>  Außerdem ein komma vor PROZESS_RUN_ID
darf nicht sein ?

nur ein kleiner Ausschnitt.
>>  #define PROZESS_DEL prozess_del
>>  #define PROZESS_DEL_ID 6
>>  {  0,   0,  PROZESS_DEL  },   PROZESS_DEL_ID

so funktioniert es.
{  0,   0,  PROZESS_DEL  },  // PROZESS_DEL_ID

greife dann über "PROZESS_DEL_ID" zu.

@Karl heinz Buchegger
funktioniert einwandfrei.

Gruß Siegfried

von Karl H. (kbuchegg)


Lesenswert?

Siegfried Saueressig schrieb:

> so funktioniert es.
> {  0,   0,  PROZESS_DEL  },  // PROZESS_DEL_ID
>
> greife dann über "PROZESS_DEL_ID" zu.
>
> @Karl heinz Buchegger
> funktioniert einwandfrei.

Ach ja?
Dann sortiere mal deine Einträge um :-)
oder ändere um in
#define PROZESS_DEL_ID 17
Compiliert weiterhin einwandfrei. Macht aber enorme Laufzeitprobleme :-)

Guter Code zeichnet sich immer dadurch aus, dass der Programmierer bei 
einem eventuellen Umbau in einem halben Jahr so wenig Fehler wie möglich 
machen kann. Jeder Zusammenhang, jede Abhängigkeit, an die man sich als 
Programmierer erinnern muss, ist eine potentielle Fehlerquelle zuviel.

von Phantomix X. (phantomix)


Lesenswert?

ach SO war das gemeint, die Zahl dahinter ist ein Kommentar... brauchen 
wir uns hier nicht wundern...


> {  0,   0,  PROZESS_DEL  },  // PROZESS_DEL_ID
>
> greife dann über "PROZESS_DEL_ID" zu.


ist kompletter Unsinn. Wenigstens stimmt jetzt dein typedef: die Zahl am 
Ende gehört also nicht mit in den code sondern ist nur ein Kommentar.

Unsere Ersetzung mit define funktioniert deshalb, weil zufällig die 
Zahlen im define mit dem Index im Array übereinstimmen. Das ist ja nicht 
weiter schlimm - solltest du mal umsortieren musst du nur die defines 
ändern...


> Guter Code zeichnet sich immer dadurch aus, dass der Programmierer
> bei einem eventuellen Umbau in einem halben Jahr so wenig Fehler
> wie möglich machen kann.

unterschreib

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.