PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Überladene Funktionen in C oder eine Alternative



Pr0gm4n
17.04.2008, 20:47
Hi erstmal,

da ich neben der "Mikrocontrollerei" auch noch Programmierung betreibe (C++, bald auch java), kenne ich vom C++ die Überladenen Funktionen

dabei definiert man einfach die gleiche Funktion (Name gleich) mit unterschiedlichen Parametern hintereinander und das Programm wählt dann selbstständig aus, welche Funktion davon zu den mitangegebenen Parametern passt.

Bei meinem Problem will ich eine Funktion schreiben, mit deren Hilfe der Benutzer Servos ansteuern kann

er soll dabei aber nicht eine bestimmte Anzahl an Servos angeben müssen, und auch nicht aus verschiedenen Funktionen auswählen müssen

ich möchte deshalb gerne irgendwie vom Programm erkennen lassen, wie viele Parameter die aufgerufene Funktion mitgesendet bekommen hat und daraufhinbedingt dann die verschiedenen Funktionen aufrufen, die dann die jeweilige Anzahl an Servos ansteuern


Jetzt wäre das mit Überladenen Funktionen wirklich sehr leicht zu erfüllen, doch in C stehen diese leider nicht zur Verfügung


Kann ich diese bei µCs verwenden oder kennt vielleicht jemand eine Alternative?

(Es sollen pro Servo int-Werte übergeben werden)


MfG Pr0gm4n

p_mork
17.04.2008, 21:13
Hallo Pr0gm4n,

was spricht gegen C++?

MfG Mark

Pr0gm4n
17.04.2008, 21:29
Hi,

nichts, ich dachte nur, man kann bei µCs nur C verwenden, oder habe ich mich da geirrt?

Wenn ja, muss ich da dann auch nur die AVR/io.h includen oder etwas anderes?


MfG Pr0gm4n

Besserwessi
17.04.2008, 22:43
Einige Teile von C++ erzeugen ziehmlich langen Code oder benötigen viel RAM. Gerade wenn man die echt objektorientierten Teile benutzt erreicht man dann schnell die Grenzen der kleinen Controller. Auch sind nicht alle der include files für c++ geeigent.

johns
18.04.2008, 01:41
hallo,

eine möglichkeit wäre es einen argumenten vektor (array) zu übergeben, so wie auch kommandozeilenparameter ins ('pc') programm kommen (bekannt als argv, oder args). und dann halt für jedes array element (servo stelldaten) die gewünschte(n) funktione(n) mittels schleife aufrufen. ein argc parameter äquivalent (argument count, länge des arrays) kannst du zur effizienzsteigerung natürlich auch implementieren.
ich hoffe das war verständlich genug, ich schlafe nämlich bereits zu ca 85% ;)

gute nacht

p_mork
18.04.2008, 07:44
Einige Teile von C++ erzeugen ziehmlich langen Code oder benötigen viel RAM. Gerade wenn man die echt objektorientierten Teile benutzt erreicht man dann schnell die Grenzen der kleinen Controller.
Das ist ein weitverbreitetes Vorurteil. Wenn man nicht gerade alle Variablen dynamisch anlegt und nicht jede Methode virtuell deklariert kann man sehr effizienten Code erzeugen, der problemlos mit C mithalten kann. Die richtig speicherfressenden Sachen wie Exceptions kann man bei AVRs sowieso nicht benutzen. Außerdem muss er jan icht gleich objektorierntiert proggen, er wollt ja nur die Möglichkeit der Funktionsübeladung.


MfG Mark

robocat
18.04.2008, 08:23
bezugnehmend auf das was johns gesagt hat kann man das so machen (zumindest am pc):

#include <stdarg.h>

funktion(const char *fmt, ...)
{
va_list ap;

va_start(ap, fmt);
printf(text, fmt, ap);
va_end(ap);
}

gruesse

Felix G
18.04.2008, 11:08
Jupp, so würde ich das auch machen...

denn um Funktionen mit einer variablen Anzahl an Parametern zu realisieren muss man sie nicht überladen. Ein schönes Beispiel ist da z.B. printf, die funktioniert auch so.

Pr0gm4n
18.04.2008, 13:03
Hi,

das mit einem Array hab ich mir auch schon überlegt:

man würde ein Array übergeben, mit sizeof() die anzahl der Elemente bestimmen und dann hätte man das gleiche Ergebnis

da ich aber nun mal dem Benutzer das ersparen will (als Array übergeben) sollen Int-Werte übergeben werden


den code von robocat verstehe ich jetzt nicht so ganz, sehe ich das richtig, dass im richtigen Programm dann kein "..." als Parameter steht?

irgendwie verwirrt mich der Code an sich schon ziemlich^^


Nun eine relativ entgültige Frage zum Überladen der Funktionen:

Was muss ich includen und kann ich das jetzt definitiv hernehmen?


wäre nett, wenn mir das noch jemand sagen könnte



MfG Pr0gm4n

Pr0gm4n
18.04.2008, 13:08
Ach ja, ich hab da noch ne Frage, die Warscheinlich keines neuen Threads würdig ist, gibt es einen Delaybefehl, der so um die 1us zählen kann?

Gibt es dazu noch eine Timeransteuerung, die sowohl auf ATMega 32 als auch auf ATMega 8 (und evtl. ATMega 16) geht?

Ich würde die Timer gerne im Programm kalibrieren lassen, dazu brauche ich das


MfG Pr0gm4n

Felix G
18.04.2008, 13:21
Das "..." bedeutet soviel wie "beliebige Anzahl an weiteren Parametern"...

ist genau wie bei printf() da kann man nach dem Format-String ja auch beliebig viele Werte übergeben.

Die Funktion muss nur wissen wieviele Parameter übergeben werden, bei printf funktioniert das z.B. ganz einfach über die Auswertung des Format-Strings (man könnte aber auch als ersten Parameter z.B. direkt die Anzahl der weiteren Parameter übergeben).

Pr0gm4n
18.04.2008, 13:36
Hi,

das Problem dabei ist für mich jetzt, dass ich dem Benutzer ja genau das ersparen will, er soll einfach ein paar Werte am Anfang definieren und dann die Funktion aufrufen können, von 1-maximal 20 Parametern

bei eurer Funktion ist das ja nicht der Fall, geht das also jetzt mit einer Überladenen Funktion? also für den µC?

und die Frage ob das "..." jetzt auch wirklich im Programmcode enthalten ist, hab ich jetzt auch noch keine Ahnung von

also, KANN ICH EINE ÜBERLADENE FUNKTION HERNEHMEN UND WAS MUSS ICH INCLUDEN???

das ist so ziemlich alles, was ich zu dem Thema noch wissen muss^^


MfG Pr0gm4n

robocat
18.04.2008, 13:39
hier wird der funktion "addiere" eine reihe von integern übergeben. va_arg(ap,int) liefert bei jedem aufruf jeweils den nächsten wert. da ich grade selber nicht weiss, wie man das ende der liste erkennt, steht als erster parameter der funktion die anzahl der übergebenen werte. das ... bleibt so stehen, der code compiliert bei mir klaglos.


#include <stdio.h> // für printf
#include <stdarg.h> // für variable parameterlisten

int addiere(const int anzahl, ...)
{
va_list ap;
int n,result=0;

va_start(ap, anzahl);
for(n=0;n<anzahl;n++)
{
result+=va_arg(ap,int);
}
va_end(ap);

return result;
}

int main()
{
// 5 argumente, nämlich die werte 1-5
int i=addiere(5,1,2,3,4,5);
printf("%d",i);
return 0;
}

vielleicht hilft das, am besten du spielst selbst ein wenig mit dem code.

gruesse

EDIT:

KANN ICH EINE ÜBERLADENE FUNKTION HERNEHMEN UND WAS MUSS ICH INCLUDEN???
nur die ruhe, nicht schreien ;)
ehrlichgesagt, ich weiss es nicht, weil ich dazu von c++ zuwenig ahnung habe. aber avr-gcc unterstützt (teilweise) c++, also könntest du es einfach mal ausprobieren.

Pr0gm4n
18.04.2008, 13:48
Hi, danke für den Code, ich bin jetzt erst mal mit meinem Orchester ein paar Tage weg, aber danke, das kann ich auch gleich brauchen^^

jetzt brauch ich für das andere Problem aber immer noch die includes und das "ja", dafür dass man Überladene Funktionen hernehmen darf....


MFG PR0gm4n

Felix G
18.04.2008, 13:54
Also theoretisch kannst du C++ verwenden (überladene Funktionen gibt es in C ja nicht), praktisch habe ich persönlich das allerdings noch nicht in einer zufriedenstellenden Art zum laufen gebracht.
(ich vermute wegen Problemen mit meinem Makefile)


Wenn du nur mit C auskommen möchtest, musst du die "..."-Variante nehmen...

Dabei muss der Benutzer übrigens nicht zwangsweise gleich die Anzahl an Parametern übergeben, man kann auch auf anderem Wege ermitteln welcher der letzte ist. Man könnte z.B. als letzten Parameter einfach ein "-1" übergeben, oder sonst irgendwas was sich eindeutig identifizieren lässt. Vielleicht ergibt sich die Anzahl der Parameter ja aber auch automatisch aus den bisher verwendeten Parametern ("wenn erster Parameter = xy kommen maximal noch 2" oder sonst irgendwas in der Richtung, was sinnvoll ist und was nicht hängt von der Funktion ab).


Ich versuche mal kurz zu erklären wie man eine Funktion mit einer beliebigen Anzahl von Parametern in C realisiert:

du benötigst die stdarg.h, in dieser sind mehrere Makros definiert:

1. va_list
das ist ein Datentyp der die nötigen Informationen für die Argumentliste enthält, um den man sich aber sonst nicht weiter kümmern muss.

2. va_start(va_list, ParamN)
muss vor der Auswertung der Parameter aufgerufen werden. va_list ist dabei natürlich der Name einer va_list (die man zuvor erstellt hat), ParamN ist der Name des letzten festgelegten Arguments (also das vor den ...).

3. va_arg(va_list, type)
liefert dir den nächsten Parameter. type ist der Datentyp des Parameters und muss bekannt sein!

4. va_end(va_list)
wenn die Parameter alle ausgewertet worden sind, muss man noch dieses Makro aufrufen.


mal ein konkretes Beispiel:

int zahlenaddieren(int a, ...) //ja, das ... steht wirklich da!
{
int ergebnis = 0;
int tmp;
va_list meineparameter;

va_start(meineparameter, a)

do
{
tmp = va_arg(meineparameter, int);
ergebnis = ergebnis + tmp;
} while (tmp != 0);

va_end(meineparameter)
}

Diese Funktion sollte sämtliche Zahlen addieren die man ihr übergibt, bis eine 0 kommt. D.h. man müsste hier also am Ende immer eine 0 mit übergeben, damit die Funktion weiß wann sie aufhören soll.

robocat
18.04.2008, 14:25
da haben wir ja beinahe dasselbe gebastelt ;)

ausser dass bei dir 2 strichpunkte fehlen, und, das ist interessant, der erste parameter (a) nicht von va_arg erfasst wird. man müsste also "ergebnis" vor der while-schleife mit ergebnis=a; "vorladen". nicht als kritik missverstehen, ist nur als hinweis gemeint.

gruesse

Pr0gm4n
18.04.2008, 14:43
Hi,

ich hab das jetzt in etwa verstanden, werde mal versuchen, was sich da so basteln lässt, um meinen Code zusammenzukriegen

die includes für überladene Funktionen sind ja die gleichen, wie die die ich auch auf dem PC verwende, oder?

dann probier ichs bald mal aus, soll u.a. halt eine art Servocontroller werden, wie es ihn zu kaufen gibt, blos viel billiger

dann kann man das ganze selbst als "Bausatz" auf einer Lochraster für insgesamt unter 5 € zusammenbauen und muss nur meinen Compilierten Code reinladen

die Funktion soll aber auch in eine Art Servo-Library, mit der man dann nach includen auch beliebig die angeschlossenen Servos ansteuern können soll


MfG Pr0gm4n

Felix G
18.04.2008, 16:37
die includes für überladene Funktionen sind ja die gleichen, wie die die ich auch auf dem PC verwende, oder? ja, eigentlich schon.



ausser dass bei dir 2 strichpunkte fehlen, und, das ist interessant, der erste parameter (a) nicht von va_arg erfasst wird. man müsste also "ergebnis" vor der while-schleife mit ergebnis=a; "vorladen".Ah stimmt, da haben sich ein paar Fehlerchen eingeschlichen...

aber naja, ich hab ja auch nie behauptet daß der code funktioniert ;)

SprinterSB
19.04.2008, 08:27
Ich verstehe nicht, warum hier überladene Funktionen gebraucht werden, auch varargs schein hier überdosiert.

1. Wenn ein Anwender 3 Servos ansteuern will, kann er zB eine Servo-FUnktion 3x aufrufen
2. Besser ist hier wohl: Der Anwender ruft die Funktion mit der Anzahl der Servos auf und liefert ein Array mit Servo-Daten mit:


typedef
{
...
} servo_t;

void servo_func (int n_servos, servo_t * servos);


In servo_func arbeitet man alle Servos ab, fährt zB alls synchron von A nach B oder so.

Zudem kann man die Anzahl der Servos in der Endanwendung immer als Konstante annehmen.


#include "servo.h"

servo_t serv[] =
{
[0] = { ...},
[1] = { ...},
...
};

... servo_func (sizeof (serv) / sizeof (serv[0]), serv);

Felix G
19.04.2008, 10:12
Naja, wir wissen ja nicht wofür er die unterschiedliche Parameteranzahl benötigt.

Möglicherweise geht es ja um eine Funktion mit z.B. 5 Parametern, von denen aber vielleicht nur 2 zwingend notwendig sind, und 3 optional. Da könnte varargs dann durchaus sinnvoller sein als dein Vorschlag.


Es kommt halt ganz auf den konkreten Anwendungsfall an, welches Sprachmittel zur Umsetzung verwendet werden sollte.

Pr0gm4n
20.04.2008, 15:59
Hi,

@SprinterSB: hast du die Posts mal gelesen? Ich hab bereits deine Lösung geschrieben, doch der Anwender soll die Parameterzahl nicht mitliefern müssen, die Servos nicht nacheinander Ansteuern müssen, und er soll sie auch nicht in ein Array packen müssen

In dem fall geht das mit den varargs auch nicht, di ebrauch ich jetzt für was anderes


Ich mach das jetzt einfach mit Überladenen Funktionen


MfG Pr0gm4n