Forum: Mikrocontroller und Digitale Elektronik Kleine Warnung im Bootloader Tutourial


von Ingo (Gast)


Lesenswert?

Hallo, im Artikel:
http://www.mikrocontroller.net/articles/AVR_Bootloader_in_C_-_eine_einfache_Anleitung
wird eine Funktion deklariert:
1
 void (*start)( void ) = 0x0000;        /* Funktionspointer auf 0x0000 */
mein Atmel Studio 6 warnt allerdings mit:
1
Warning  1  initialization makes pointer from integer without a cast [enabled by default]

ein
1
void (*start)( void ) = (int*)0x0000;        /* Funktionspointer auf 0x0000 */
behebt die Warnung nicht, es kommt:
1
Warning  1  initialization from incompatible pointer type [enabled by default]

Was kann man denn dagegen tun?


Ingo

von Daniel V. (danvet)


Lesenswert?

Vielleicht:
void (*start)(void) = (void*)0x0000
?

von Ingo (Gast)


Lesenswert?

Daniel V. schrieb:
> Vielleicht:
> void (*start)(void) = (void*)0x0000
> ?


Die Warnung ist jedenfalls weg! Ich verstehe die ganze Sache aber nicht.
start() ist ein Funktionspointer auf eine Adresse, richtig? Warum dann 
die Adresse als (void*) casten?


Ingo

von Karl H. (kbuchegg)


Lesenswert?

Ingo schrieb:

> Die Warnung ist jedenfalls weg! Ich verstehe die ganze Sache aber nicht.
> start() ist ein Funktionspointer auf eine Adresse, richtig?

Richtig.

Und damit hattest du eine Initalisierung (Betrachtung der Datentypen)

  Funktionspointer = ganze Zahl

Und das passt nun mal von den Datentypen her nicht.

  Funktionspointer = Funktionspointer

würde besser passen. Also sollte man die 0 zu einem Funktionspointer 
casten. Am besten führt man sich dafür einen typedef ein. Sonst werden 
die Typschreibweisen schnell unübersichtlich.
1
typedef void (*voidFktPtr)(void)
2
3
  voidFktPtr start = (voidFktPtr)0x0000;

> Warum dann
> die Adresse als (void*) casten?

Weil definitionsgemäss ein void-Pointer mit allen anderen Pointer-Typen 
kompatibel ist.


Ihr müsst anfangen, Datentypen ernst zu nehmen. Das ist wie in der 
Physik die Einheiten. Da kann hundert mal stehen

     x = 3 * t

wenn x die Einheit m/s hat (also eine Geschwindigkeit ist) und t die 
Einheit °C hat (also eine Temperatur ist), dann ist diese Berechnung 
einfach nur Unsinn, auch wenn man das numerisch selbstverständlich so 
rechnen kann. 3 mal beispielsweise 25 kann man ausrechnen, das macht 75 
und diese 75 kann ich an x zuweisen. Rein technisch ist das überhaupt 
kein Problem. Aber das Ergebnis sagt nichts aus und ist unsinnig. In der 
Betrachtung der Einheiten links und rechts vom = sehe ich, dass ich 
gerade im Begriff bin, Blödsinn auszurechnen. In der Programmierung 
übernehmen die Datentypen mehr oder weniger (auch) diese Aufgabe und 
werden vom Compiler überprüft.

von Daniel V. (danvet)


Lesenswert?

siehe auch:
http://www.mikrocontroller.net/articles/Funktionszeiger_in_C

*start() ist ein Zeiger auf eine Funktion. Der Compiler möchte wissen, 
wie diese Funktion definiert ist.
"void *start(void)" sagt, dass die aufzurufende Funktion keinen 
Rückgabewert hat und keine Aufrufparameter. Die Zeiger-Addresse, die man 
dann setzt muss vom gleichen Typ sein, also "void*", nicht "int*".

von Ingo (Gast)


Lesenswert?

Danke @Karl-Heinz und Daniel!

von Karl H. (kbuchegg)


Lesenswert?

Daniel V. schrieb:

> "void *start(void)" sagt, dass die aufzurufende Funktion keinen
> Rückgabewert hat und keine Aufrufparameter.

soweit richtig.

> Die Zeiger-Addresse, die man
> dann setzt muss vom gleichen Typ sein, also "void*", nicht "int*".

Nö.
Der Datentyp eines enstprechenden Funktionszeigers wäre

  void(*)(void)

und nicht void*.
Aber ein void* ist zu allen anderen Pointer per Definition in C immer 
Datentypkompatibel.


  double * a = (void*)0x8000;

alles ok, denn ein void-Pointer ist immer kompatibel.

  struct test * myObj;
  int * b = (void*)&myObj;

alles ok, denn ein void* ist immer datentypkompatibel.

Vorsicht mit void-Pointern! Durch ihre automatische Kompatibilität kann 
man damit auch großen Unsinn anstellen! Generell sollte man Casts als 
Waffen ansehen und niemals leichtfertig benutzen. Nur manchmal gehts 
halt nichts anders.

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.