Forum: Mikrocontroller und Digitale Elektronik Verständnisproblem typedef


von Michael_SS (Gast)


Lesenswert?

Hallo zusammen.

Ich habe in einem C code des AVR32 Studios folgenden typedef gefunden:


typedef Byte (*LCD_FontCallback)(Byte*);



Kann mir jemand erklären, was diese Zeile machen soll?
Versuche diese Zeile in meinen Codevision Compiler zu implementieren. 
Der sagt jedoch "Syntax Error".

Weiter unten im Text steht folgendes:

LCD_FontCallback      LCD_FontRead;
Byte*                    LCD_Font;

// Font Functions
Byte LCD_ReadFontData(Byte* ptr)
{
  return (*ptr);
}


Es geht hier um die Auswahl einer hinterlegten Schriftgröße für die 
Anzeige von Text auf einem LCD. Programmiert wurde der ursprünglich Code 
für einem AT32UC3 und ich versuche das ganze jetzt in einem ATMEGA64 zu 
implentieren.

Könnt ihr mir den Code erläutern?

von Sina A. (sinapse)


Lesenswert?

typedef Byte (*LCD_FontCallback)(Byte*);


LCD_FontCallback ist ein zeiger auf eine funktion, die einen zeiger auf 
einen byte erwartet und einen byte zurückgibt.

weiter unten wird eine solche funktion definiert

// Font Functions
Byte LCD_ReadFontData(Byte* ptr)
{
  return (*ptr);
}

und in der variablen LCD_FontRead festgehalten.


du bekommst wahrscheinlich ein syntax error, weil deine umgebung byte 
nicht kennt... schreib mal überall statt byte ein char hin und guck obs 
besser klappt.  dann weisst du das es daran lag

lg

von Matthias M. (matthias_m69)


Lesenswert?

typedef Byte (*LCD_FontCallback)(Byte*);

Ja, das ist ein ganz übler Syntax weil nicht offensichtlich.

Was "typedef unsigned int uint;" macht, ist klar, oder? Der Typ "uint" 
kann jetzt anstatt "unsigned int" verwendet werden, bedeutet aber das 
selbe.

Links steht also der existierende Typ, recht steht der neue Name.

Bei Deinem Beispiel ist "rechts" der neue Name: LCD_FontCallback

Der Rest ist der bestehende Typ, also "Byte (*)(Byte*)", oder 
ausgeschrieben, ein Zeiger auf eine Funktion, die als erstes und 
einziges Argument einen "Byte*" nimmt und ein "Byte" zurück gibt.

Du kannst in C also Zeiger auf Funktionen anlegen, z.B.:

typedef double (*SomeMath)(double a, double b);

double add(double a, double b) { return a+b; }
double sub(double a, double b) { return a-b; }

SomeMath myFunction = add; // speichere die Adresse der Funktion "add()"
double z = *myFunction(10, 20); // rufe die gespeicherte Funktion auf
myFunction = sub;
double z = *myFunction(10, 20);

von Michael_SS (Gast)


Lesenswert?

Danke für Eure Hilfe.

Habe "unsigned char" statt "Byte" geschrieben. Und nun geht es.
Habe jetzt auch die Syntax verstanden.

Danke nochmals.

von Karl H. (kbuchegg)


Lesenswert?

Matthias M. schrieb:
> typedef Byte (*LCD_FontCallback)(Byte*);
>
> Ja, das ist ein ganz übler Syntax weil nicht offensichtlich.
>
> Was "typedef unsigned int uint;" macht, ist klar, oder? Der Typ "uint"
> kann jetzt anstatt "unsigned int" verwendet werden, bedeutet aber das
> selbe.
>
> Links steht also der existierende Typ, recht steht der neue Name.

<Nitpicking>

Erklär es nicht mit Ausdrücken wie 'links' und 'rechts'.

Ein typedef funktioniert im Grunde so, dass man sich die Definition 
einer Variablen vorstellt, die vom gesuchten Typ sein sein.
Schreibt man dieser Variablendefinition dann ein 'typedef' davor, dann 
mutiert der Name der Variablen zum Namen eines neues Datentyps, der ein 
Alias für diesen Datentyp sein soll.

Da man eine unsigned int Variable so definieren würde
1
  unsigned int myVar;

wird der Name an der Stelle 'myVar' durch Voranstellen von 'typedef' zum 
Namen des neuen Datentyps
1
  typedef unsigned int uint;

Da man ein Array der Länge 20 vom char so definieren würde
1
  char myText[20];

erhält man durch Voranstellen von 'typedef' einen neuen Datentyp
1
  typedef char str[20];
einen neuen Datentyp namens 'str', der den Datentyp 'Array von 20 char' 
repräsentiert.

Da man einen Funktionspointer mit dem Namen Callback als Variable so 
definieren würde
1
    void (*Callback)( void );
(für Funktionen die keine Argumente nehmen und auch keinen Rückgabewert 
liefern), wird das ganze durch Voranstellen von 'typedef'
1
  typedef (*callbackFnct)(void);
zu einem neuen Datentyp namens 'callbackFnct', der ein Alias für den 
genannten Datentyp eines Funktionspointers ist.
Und ja: Anzahl Argumente, Datentyp der Argumente und Datentyp des 
Rückgabewertes sind alles Bestandteile des Typs eines Funktionspointers.


Das ist die Idee hinter 'typedef': Nimm eine geeignete Definition einer 
Variablen mit genau dem Typ den du brauchst und stelle diesem ein 
typedef davor. Dann mutiert der Name der Variable zum Namen des neuen 
einzuführenden Datentyp-Names, der einen Alias dazu darstellt.


Alias == andere Schreibweise.

: Bearbeitet durch User
von W.S. (Gast)


Lesenswert?

Karl Heinz schrieb:
> Ein typedef funktioniert im Grunde so...

Naja, man kann's auch kompliziert erklären.

O-Ton aus einem alten C-Buch:

"Mit 'typedef' kann man einem bereits existierenden Typ einen neuen 
Namen geben."

Dieses typedef ist deshalb im Allgemeinen eher was herzlich Nutzloses. 
Als hilfreich habe ich das nur in einem Falle empfunden: Wenn man bei 
Struct-Variablen nicht immer 'struct' dazu schreiben will. Dann kann man 
mit typedef die Hinschreiberei etwas straffen.


W.S.

von Karl H. (kbuchegg)


Lesenswert?

W.S. schrieb:
> Karl Heinz schrieb:
>> Ein typedef funktioniert im Grunde so...
>
> Naja, man kann's auch kompliziert erklären.
>
> O-Ton aus einem alten C-Buch:
>
> "Mit 'typedef' kann man einem bereits existierenden Typ einen neuen
> Namen geben."

Schon.
Aber das sagt nichts darüber aus, wie die Syntax zustande kommt bzw. 
gibt einem eine leicht zu merkende Daumenregel in die Hand, wie ein 
typedef zu lesen ist.

> Dieses typedef ist deshalb im Allgemeinen eher was herzlich Nutzloses.

Sehe ich nicht so.
Ein typedef ist perfekt geeignet um die Tipp-Faulheit des Programmierers 
bei Datentypen zu unterstützen.
Und gerade bei Funktionspointern spart einem ein typedef des öfteren 
eine Menge Kopfzerbrechen und lange Argumentlisten in 
Funktionsdefinitionen. Letzten Endes sind Dinge wie uint8_t, uint16_t ja 
auch nichts anderes als vordefinierte typedefs.

: Bearbeitet durch User
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.