Forum: Mikrocontroller und Digitale Elektronik [ATmega] Pointer Umwandlung in C++ (C code)


von Stefan K. (sk-ac)


Lesenswert?

Hallo,

ich versuche C code nach C++ zu bringen.
Bisher lief es auch recht gut, nur bei dem Code für die FAT stehe ich 
vor einem Problem:
1
uint8_t FAT::fat_dir_entry_read_callback(uint8_t* buffer, offset_t offset, void* p)
2
{
3
    struct fat_read_dir_callback_arg* arg = p;
4
    struct fat_dir_entry_struct* dir_entry = arg->dir_entry;

Der Compiler meldet:

invalid conversion from 'void*' to 'fat_read_dir_callback_arg*'

Ganz sauber ist das ja auch wirklich nicht, aber unter C läuft der Code 
durch.
Jemand eine Idee?

Danke,
Stefan

von Karl H. (kbuchegg)


Lesenswert?

Stefan Kuhne schrieb:

> Ganz sauber ist das ja auch wirklich nicht, aber unter C läuft der Code
> durch.
> Jemand eine Idee?

Ja.
Wer Code von C nach C++ portiert, sollte über die Unterschiede der 
Sprachen Bescheid wissen :-)

In C ist es legal einen void Pointer an einen anderen zuzuweisen.
In C++ aber nicht. Da muss man casten (sofern man sich sicher ist, dass 
die Zuweisung an sich in Ordnung ist)

von Stefan K. (sk-ac)


Lesenswert?

Hallo,

das mit dem Cast hatte ich versucht und wollte es mit reinschreiben.
Das hatte ich so probiert:
1
struct fat_read_dir_callback_arg* arg = (fat_read_dir_callback_arg) p;

Der Compiler sagt:

no matching function for call to 
'fat_read_dir_callback_arg::fat_read_dir_callback_arg(void*&)'

Mist, wenn man die Meldung ganz liest sieht man was er will.

Aber wird das nicht eine Entlosschleife?
Obwohl wenn ich jedes Element dann einzeln zuweise geht sollte das gehen 
...

Danke,
Stefan

von Rene H. (Gast)


Lesenswert?

Naja, p ist ja auch ein Pointer, nach C könnte das so aussehen
1
struct fat_read_dir_callback_arg* arg = (fat_read_dir_callback_arg*) p;

Sauber wäre
1
struct fat_read_dir_callback_arg* arg = static_cast<fat_read_dir_callback_arg*>(p);

von Hc Z. (mizch)


Lesenswert?

Dein Cast tut was anderes als die C-Zuweisung.
>
1
> struct fat_read_dir_callback_arg* arg = (fat_read_dir_callback_arg *) p;
2
                                                            ---------^
Versuch's mal so.

von Stefan K. (sk-ac)


Lesenswert?

Hallo,

man ist man mal ein halbes Jahr weg von C und macht was ohne Pointer und 
dann passiert sowas.

Aber die "static_cast" Lösung werde ich auch nutzen.

Vielen Dank,
Stefan Kuhne

von tuppes (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Da muss man casten (sofern man sich sicher ist, dass
> die Zuweisung an sich in Ordnung ist)

Und das ist der Knackpunkt: Wenn man sich da sicher sein kann, dann kann 
man auch das API typsicher machen.

Die Frage ist: Warum ist der Pointer void* und nicht struct 
fat_read_dir_callback_arg* ?

Wenn es keinen schlagenden Grund gibt, könnte man drüber nachdenken, das 
zu ändern und in Zukunft ein C++-API mit sicherer Typprüfung zu haben. 
Für den, der das API benutzt, ist das ein Riesenvorteil.

von Stefan K. (sk-ac)


Lesenswert?

Hallo,

tuppes schrieb:

> Wenn es keinen schlagenden Grund gibt, könnte man drüber nachdenken, das
> zu ändern und in Zukunft ein C++-API mit sicherer Typprüfung zu haben.
> Für den, der das API benutzt, ist das ein Riesenvorteil.


das dachte ich auch, nur wollte ich erstmal den Code durch den Compiler 
bekommen. Nicht das ich da arbeit reinstecke und dann hängt es irgendwo.

Stefan Kuhne

von Karl H. (kbuchegg)


Lesenswert?

tuppes schrieb:

> Die Frage ist: Warum ist der Pointer void* und nicht struct
> fat_read_dir_callback_arg* ?

Ist natürlich eine gute Frage.
Ich habs nicht angesprochen, weil das ganze danach stinkt, dass der void 
Pointer in Wirklichkeit auf ein Byte-Array zeigt. Könnte ein gelesener 
Sektor oder sowas sein.
Auch das 'callback' im Funktionsnamen hat mich stutzig gemacht. Ähnlich 
wie die void* beim qsort Callback. Und da ist dann auch schon das 
Stichwort, wie man so etwas typsicher hinkriegen kann: std:sort 
studieren.

Gerade bei I/O Sachen kommt man manchmal u so wilde Casts nicht rum.

Aber ich geb dir prinzipiell uneingeschränkt recht. Sobald void* im 
Spiel ist, sollte man zuerst danach trachten, den void* an sich 
loszuwerden.

von tuppes (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Auch das 'callback' im Funktionsnamen hat mich stutzig gemacht. Ähnlich
> wie die void* beim qsort Callback.

Bei qsort sollen ja gerade beliebige Arrays sortierbar sein, darum 
darf über den Grundtyp keine Angabe gemacht werden. qsort selber ist 
voll generisch, die Implementierung für bestimmte Typen geschieht allein 
in der zugehörigen compare-Funktion.

Auch im Fall oben gibt sich das API generisch, der Code ist es aber 
überhaupt nicht. Das ist ohne genaue Doku unbenutzbar.

Ein fast sicherer Indikator für einen solchen Fehler ist das Fehlen 
eines zum Pointer gehörenden size-Parameters - die Größe des Objekts ist 
also in Wahrheit doch vorgegeben.

Ich würde meinen, derjenige, der das C-API definiert hat, hat nicht 
richtig nachgedacht. Oder hatte nicht genug Erfahrung mit C, um die 
Fallstricke zu kennen. Jedenfalls ist jetzt der Zeitpunkt, das zumindest 
für C++-Programmierer zu korrigieren.

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.