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


von Mirco (Gast)


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:
1
void MeineFunktion(FrameID wert)
2
{
3
...
4
}
Beispiel: &MeineFunktion = 0x1234
1
byte array[2];
2
array[0] = MSB Addresse auf Funktion; hier: 0x12
3
array[1] = LSB Addresse auf Funktion; hier: 0x34
4
byte* datapointer = &array[0];

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

von Karl H. (kbuchegg)


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

von Rolf Magnus (Gast)


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
1
typedef void(*Callback_t)(FrameID);
2
3
Callback_t Callback;
4
5
Callback = (Callback_t)datapointer;

von Mirco (Gast)


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

von Rolf Magnus (Gast)


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.

von Mirco (Gast)


Lesenswert?

Hallo!

Und wie löse ich dieses Problem?

Gruß
Mirco

von Mark B. (markbrandis)


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.

1
#include <stdio.h>
2
typedef unsigned char byte;
3
typedef unsigned int  FrameID;
4
typedef void(*Callback_t)(FrameID);
5
6
void meineFunktion(FrameID wert)
7
{
8
  printf("FrameID: %d\n", wert);
9
}
10
11
int main()
12
{
13
  byte zahl = 4;
14
15
  byte array[2];
16
  array[0] = 0x12; //MSB
17
  array[1] = 0x34; //LSB
18
  byte* datapointer;
19
  datapointer = (byte*)(array[0] << 8) + array[1];
20
21
  printf("datapointer hat den Wert: %p\n", datapointer);
22
23
  Callback_t Callback;
24
  Callback = (Callback_t)datapointer;
25
  
26
  printf("Callback hat den Wert:    %p\n", Callback);
27
  //Callback = &meineFunktion;
28
29
  (*Callback)(zahl);
30
31
  return 0;
32
}

von Karl H. (kbuchegg)


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)

von Mark B. (markbrandis)


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?

von Karl H. (kbuchegg)


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.

von Mirco (Gast)


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ß.

von Mirco (Gast)


Lesenswert?

HAB'S!

Diese Lösugn habe ich zwar vorher auch schon probiert, dieses mal habe 
ich aber die typedef-Definition verwendet:
1
Callback_t* pCallback;
2
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

von Karl H. (kbuchegg)


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.

von Mirco (Gast)


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 ...

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.