Forum: Compiler & IDEs Funktionen konvertieren


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Aabeku K. (aabeku)


Lesenswert?

Hi,

angenommen man hat eine Funktion vom Type:

static int eeprom_get(char adr, char* ptr);

Ich möchte aber nicht jedes mal meinen Pointer und die EEPROM-Adresse 
mitgeben. Wenn man einer Funktion feste Parameter übergibt, sodass kann 
man dann die Funktionen so "umcasten"?

int (*eeprom_get_parameter)(void) = eeprom_get(parameter_adr, 
&parameter);


 - "Parameter_adr" ist die konstante EEPROM-Adresse wo die Daten 
hinterlegt sind.
 - "&Parameter" ist konstante Pointer zur Addresse im RAM, wo der Wert 
von "parameter" hinterlegt wird.

Gruß

P.S.: Ich rede hier von der Programmiersprache C und dem Compiler XC8 
und IDE MPLAB. Letztere beide sind von Microchip.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Das nennt sich Currying und wird so nur von funktionalen Sprachen 
unterstützt (z.B. Scala). In C++ gibt es dafür std::bind oder etwas 
schöner Lambdas (mit Cloure).

In C geht das nicht wirklich. Sofern die Parameter-Ausdrücke immer 
vorhanden sind, kannst du einfach ein Makro definieren. Oder beide Werte 
in ein struct packen, welches du an eine Hilfs-Funktion übergibst, die 
dann die beiden Werte an eeprom_get übergibt; das ist dann ein 
semi-OOP-Ansatz.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Niklas G. schrieb:
> Sofern die Parameter-Ausdrücke immer vorhanden sind, kannst du einfach
> ein Makro definieren.

So klingt mir seine Beschreibung, und in der Tat könnte man das mit 
einem Makro machen.
1
char eeprom_data;
2
3
#define EEPROM_ADDRESS 42
4
#define EEPROM_GET() eeprom_get(EEPROM_ADDRESS, &eeprom_data)
5
6
// ...
7
8
  EEPROM_GET();
9
  // ...
10
  EEPROM_GET();

Schön ist natürlich was anderes. ;-)

von Aabeku K. (aabeku)


Lesenswert?

Ja das ist genau was ich meinte.

Schön ist es wirklich nicht. Auch ein Workaround sind Wrapper.
1
int eeprom_get_parameter(void){
2
   return eeprom_get(PARAMTER_ADR, &parameter);
3
}

Ist aber genau so wenig schön wie Macros.

Schade das es nicht geht :/ Hätte einiges schöner gemacht.

Danke für die Antworten :)

: Bearbeitet durch User
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Aabeku K. schrieb:
> Ist aber genau so wenig schön wie Macros.

Mach es "static inline". Schöner als ein Makro allemal, und du hast ein 
paar Prüfungen mehr durch den Compiler.

von Frank K. (fchk)


Lesenswert?

Aabeku K. schrieb:

> static int eeprom_get(char adr, char* ptr);

Mach doch ein:

static void eeprom_set_addr(char adr, char* ptr);

und ein dazugehöriges

static int eeprom_get_inc(void);

das dann den Wert aus adr nach *ptr schreibt und beides anschließend 
inkrementiert. Ebenso wäre bei Bedarf ein static int 
eeprom_get_dec(void); denkbar.

fchk

von Wilhelm M. (wimalopaan)


Lesenswert?

Aabeku K. schrieb:
> Ja das ist genau was ich meinte.
>
> Schön ist es wirklich nicht. Auch ein Workaround sind Wrapper.
>
>
1
> int eeprom_get_parameter(void){
2
>    return eeprom_get(PARAMTER_ADR, &parameter);
3
> }
4
> 
5
>

Das ist doch genau das, was Du wolltest! Kannst Du `inline` deklarieren 
und ab in die entsprechende Header-Datei.

Was findest Du daran unschön?

Vielleicht möchtest Du es aber eher so benutzen können?
1
void f() {
2
    int v = eeprom_get(Parameter_A);
3
}

von Wilhelm M. (wimalopaan)


Lesenswert?

Niklas G. schrieb:
> Das nennt sich Currying und wird so nur von funktionalen Sprachen
> unterstützt (z.B. Scala). In C++ gibt es dafür std::bind oder etwas
> schöner Lambdas (mit Cloure).

Aus seiner Beschreibung sehe ich nicht, dass er eine N-stellige Funktion 
auf N Aufrufe einstelliger Funktionen abbilden will.

> In C geht das nicht wirklich.

In GCC kann man lokale Funktionen definieren als Erweiterung. Vielleicht 
geht das bei dem XC8 auch?Damit könnte man dann tatsächlich 
"schönfinkeln" aka currying.

von Peter D. (peda)


Lesenswert?

Ich mag das nicht, überall durcheinander im Code vom EEPROM lesen oder 
schreiben.
Ich lege mir daher ein Struct an, das alle Variablen enthält, die im 
EEPROM gesichert werden sollen. Und dann wird nur einmalig die Struct 
aus dem EEPROM gelesen, bzw. dahin gesichert.
Damit muß man keine Extrawurst für alle EEPROM-Variablen braten. Es sind 
ganz normal zugreifbare Variablen, die nach dem Reset aus dem EEPROM 
initialisiert werden.

Und das Sichern der Struct in den EEPROM erfolgt als Hintergrundtask 
(per Polling in der Mainloop), damit für die Schreibdauer die 
Applikation nicht angehalten werden muß.

von W.S. (Gast)


Lesenswert?

Aabeku K. schrieb:
> angenommen man hat eine Funktion vom Type:
>
> static int eeprom_get(char adr, char* ptr);
>
> Ich möchte aber nicht...

Wenn du so eine Funktion hast und sie dir nicht gefällt, dann schreib 
dir einfach eine bessere Funktion.

Gerade EEPROMs werden recht häufig seriell betrieben, weswegen da ein 
char* Zeiger nicht wirklich hinpaßt.

Selbst bei auf dem Chip eingebautem EEPROM ist es oft so, daß es feste 
HW-Register gibt, wo man Adresse und Sollinhalt hineinschreibt und dann 
ein Schreiben auslöst oder nur Adresse und Lesen auslösen und dann den 
Istinhalt aus einem HW-Register holen.

Irgendwelche Präprozessor-Akrobatik halte ich für übel, denn sie macht 
das Ganze nur undurchsichtiger und die vorhandene Funktion nicht besser.

W.S.

von A. S. (achs)


Lesenswert?

Aabeku K. schrieb:
> int (*eeprom_get_parameter)(void) = eeprom_get(parameter_adr,
> &parameter);
1
int eeprom_get_parameter(void) { 
2
  return eeprom_get(parameter_adr, &parameter);
3
}

: Bearbeitet durch User
von Noch ein Kommentar (Gast)


Lesenswert?

> Schön ist es wirklich nicht. Auch ein Workaround sind Wrapper.

Tja, unter den 10.000 C++23 Features findest du mindestens ein dutzend 
Features, mit denen du dein "umcasten" bauen kannst.

Musst dich halt entscheiden. Entweder eine Sprache, in der du dich auf 
struct[] und Wrapper beschränken musst. Oder eine Sprache, bei der du 
erst mal einen Kubikmeter Lehrbücher und Spezifikationen durcharbeiten 
musst.

von Wilhelm M. (wimalopaan)


Lesenswert?

Noch ein Kommentar schrieb:
>> Schön ist es wirklich nicht. Auch ein Workaround sind Wrapper.
>
> Tja, unter den 10.000 C++23 Features findest du mindestens ein dutzend
> Features, mit denen du dein "umcasten" bauen kannst.
>
> Musst dich halt entscheiden. Entweder eine Sprache, in der du dich auf
> struct[] und Wrapper beschränken musst. Oder eine Sprache, bei der du
> erst mal einen Kubikmeter Lehrbücher und Spezifikationen durcharbeiten
> musst.

Und Du hast den Beitrag nicht gelesen.

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]
  • [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.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.