www.mikrocontroller.net

Forum: Compiler & IDEs CCE: Casten eines Funktionspointers von einem Byte-Pointer


Autor: Mirco (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Ich programmiere gerade eine Firmware in C für einen MSP430 unter Code 
Composer Studio v4 von Ti.
In meinem Programm bekommt eine Funktion u.a. einen byte-Pointer, der 
auf ein entsprechendes Array zeigt, übergeben.

In diesem Array stehen serialisierte Daten, die meine Funktion 
entsprechend wieder auspacken muss. Das klappt soweit ganz gut, nur bei 
Funktionspointern hapert es.
Egal, wie ich es drehe und wende bekomme ich immer irgendwelche 
Kompiler-Warnungen und/oder -Fehler.

Wie kann ich einen byte-Pointer in einen Funktionspointer casten?

Danke für Eure Hilfe!

Gruß
Mirco

P.S.:
byte = typedef unsigned char

P.P.S.:
Pseudocode:
void MeineFunktion(FrameID wert)
{
...
}
Beispiel: &MeineFunktion = 0x1234
byte array[2];
array[0] = MSB Addresse auf Funktion; hier: 0x12
array[1] = LSB Addresse auf Funktion; hier: 0x34
byte* datapointer = &array[0];

Funktionspointer zeigt auf "void (*Callback) (FrameID wert)"
Gesucht ist also:
void (*Callback) (FrameID wert);
Callback = *datapointer
Ziel: Callback = 0x1234

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

Bewertung
0 lesenswert
nicht lesenswert
Bei Funktionspointern ist es immer eine extrem gute Idee, sich für den 
Datentyp des Funktionspointers einen typedef zu erzeugen.

Damit kannst du dann ganz leicht casten.
http://www.mikrocontroller.net/articles/FAQ#Funktionszeiger

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mirco schrieb:
> Egal, wie ich es drehe und wende bekomme ich immer irgendwelche
> Kompiler-Warnungen und/oder -Fehler.

"irgendwelche"? Keine ganz konkreten, die du posten könntest?

> Wie kann ich einen byte-Pointer in einen Funktionspointer casten?

So wie du es mit jedem anderen Typ auch tun würdest, indem du den 
Zieltyp in Klammern davor schreibst. Zur besseren Lesbarkeit bietet sich 
ein typedef an.

> Funktionspointer zeigt auf "void (*Callback) (FrameID wert)"
> Gesucht ist also:
> void (*Callback) (FrameID wert);
> Callback = *datapointer
> Ziel: Callback = 0x1234
typedef void(*Callback_t)(FrameID);

Callback_t Callback;

Callback = (Callback_t)datapointer;

Autor: Mirco (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Vielen Dank für die schnellen Antworten.

Rolf Magnus schrieb:
> "irgendwelche"? Keine ganz konkreten, die du posten könntest?

"void *" is incompatible with parameter of type "void (*)(FrameID)"
und
"nonstandard conversion between pointer to function and pointer to data"
zum Beispiel.
Letzteres ist mein Hauptproblem (die anderen resultieren auf den 
kläglichen Verscuehn, den Pointer richtig zu casten) und kommt auch bei 
der Verwendung von typedef, wie es von euch vorgeschlagen wurde.

Gruß
Mirco

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mirco schrieb:
> "void *" is incompatible with parameter of type "void (*)(FrameID)"
> und "nonstandard conversion between pointer to function and pointer to
> data" zum Beispiel.

Ah, ok. Dann hast du wahrscheinlich den ANSI- bzw. ISO-Modus 
eingestellt. In ISO-C sind Konvertierungen zwischen Datenzeigern und 
Funktionszeigern generell verboten.

Autor: Mirco (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Und wie löse ich dieses Problem?

Gruß
Mirco

Autor: Mark Brandis (markbrandis)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So vielleicht?
Dieses Beispiel kompiliert einwandfrei, allerdings geht es zur Laufzeit 
in die Hose, weil an Adresse 0x1234 halt irgendwas liegen kann. Wenn man 
die auskommentierte Zeile mit kompiliert, läuft's.

#include <stdio.h>
typedef unsigned char byte;
typedef unsigned int  FrameID;
typedef void(*Callback_t)(FrameID);

void meineFunktion(FrameID wert)
{
  printf("FrameID: %d\n", wert);
}

int main()
{
  byte zahl = 4;

  byte array[2];
  array[0] = 0x12; //MSB
  array[1] = 0x34; //LSB
  byte* datapointer;
  datapointer = (byte*)(array[0] << 8) + array[1];

  printf("datapointer hat den Wert: %p\n", datapointer);

  Callback_t Callback;
  Callback = (Callback_t)datapointer;
  
  printf("Callback hat den Wert:    %p\n", Callback);
  //Callback = &meineFunktion;

  (*Callback)(zahl);

  return 0;
}


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

Bewertung
0 lesenswert
nicht lesenswert
Eventuell könnte man den Compiler mit einer union austricksen.
Allerdings: Wenn sich der Compiler standhaft weigert einen Datenpointer 
zu einem Funktionspointer umzucasten, dann denke ich mal, wird das 
seinen Grund haben (inkompatible Länge von Pointern)

Autor: Mark Brandis (markbrandis)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> wird das seinen Grund haben (inkompatible Länge von Pointern)

Ähm, wie genau dies? Zeigervariablen an sich haben doch immer die 
gleiche Länge bzw. Größe? Oder ist damit gemeint dass der Adressraum für 
verschiedene Speicherbereiche unterschiedlich groß sein kann, z.B. auf 
einem Prozessor mit Harvard-Architektur?

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

Bewertung
0 lesenswert
nicht lesenswert
Mark Brandis schrieb:
> Karl heinz Buchegger schrieb:
>> wird das seinen Grund haben (inkompatible Länge von Pointern)
>
> Ähm, wie genau dies? Zeigervariablen an sich haben doch immer die
> gleiche Länge bzw. Größe?

No.

Dafür gibt es keine Garantie.

Ein void* kann alle Datenzeiger aufnehmen. Aber kein Mensch sagt, dass 
Funktionszeiger dieselbe Länge haben müssen. Auch nicht der C-Standard.

> Oder ist damit gemeint dass der Adressraum für
> verschiedene Speicherbereiche unterschiedlich groß sein kann, z.B. auf
> einem Prozessor mit Harvard-Architektur?

Harvard ist schon ein gutes Stichwort.
Wenn dein µC nur 256 Bytes SRAM hat, dann genügt es, wenn man einen 
Datenpointer (einen int* oder einen char* oder ...) nur 1 Byte groß 
macht. Wenn er aber zb 1K für Programmcode (zb in einem Flash) hat, dann 
reicht für Funktionspointer ein einzelnes lausiges Byte klarerweise 
nicht aus.


Wie das jetzt bei diesem Compiler und beim MSP ist, weiß ich nicht. 
Normalerweise weigern sich Compiler spätestens nach einem Cast nicht 
mehr. Wenn dieser Compiler es trotzdem tut, könnte es einen Grund dafür 
geben.

Autor: Mirco (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Mein Problem ist nicht das:
Mark Brandis schrieb:
> datapointer = (byte*)(array[0] << 8) + array[1];

Sondern das:
Mark Brandis schrieb:
> Callback = (Callback_t)datapointer;

Karl heinz Buchegger schrieb:
> enn dein µC nur 256 Bytes SRAM hat, dann genügt es, wenn man einen
> Datenpointer (einen int* oder einen char* oder ...) nur 1 Byte groß
> macht. Wenn er aber zb 1K für Programmcode (zb in einem Flash) hat, dann
> reicht für Funktionspointer ein einzelnes lausiges Byte klarerweise
> nicht aus.
>
>
> Wie das jetzt bei diesem Compiler und beim MSP ist, weiß ich nicht.
> Normalerweise weigern sich Compiler spätestens nach einem Cast nicht
> mehr. Wenn dieser Compiler es trotzdem tut, könnte es einen Grund dafür
> geben.
>

Ich glaube über 256 Byte RAM und 1kByte Programmcode brauchen wir nicht 
reden. Wir reden hier von mehreren kByte. ;)

Habe mal mit sizeof die Größe von zwei drei Pointern überprüft. Alle 
waren 2 Byte groß.

Autor: Mirco (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
HAB'S!

Diese Lösugn habe ich zwar vorher auch schon probiert, dieses mal habe 
ich aber die typedef-Definition verwendet:
Callback_t* pCallback;
pCallback = (Callback_t*)datapointer;
lautet die Lösung.

Als bei mir noch "void(*)(FrameID)" satt "Callback_t" stand, hat der 
Compiler es nicht akzeptiert...

Danke euch allen!

Gruß
Mirco

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

Bewertung
0 lesenswert
nicht lesenswert
Mirco schrieb:

> Als bei mir noch "void(*)(FrameID)" satt "Callback_t" stand, hat der
> Compiler es nicht akzeptiert...

Grrrrrrr

Zitat
> Letzteres ist mein Hauptproblem (die anderen resultieren auf den
> kläglichen Verscuehn, den Pointer richtig zu casten) und kommt auch bei
> der Verwendung von typedef, wie es von euch vorgeschlagen wurde.

Es hat schon seinen Grund, warum ich dir als erstes einen typedef für 
den Funktionspointer vorgeschlagen habe. Man verhaut sich leicht mit der 
Syntax, wenn man jedesmal Funktionspointer-Datentypen komplett 
ausschreiben muss.

Autor: Mirco (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab doch deinen Ratschlag zu Herzen genommen und umgesetzt. Nur wurde in 
dem von euch geschriebenen Beispielcode der Datenpointer direkt in die 
Callback-Funktion gecastet und nicht als Pointer, was jetzt entgültig 
die Lösung war ...

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.