Forum: Mikrocontroller und Digitale Elektronik Syntax Frage in C


von Dave C. (dave_chappelle)


Lesenswert?

Hi Zusammen..

Ich habe ne Frage bezüglich Syntax oder ob das überhaupt geht.

Ich habe 10 Funktionen, die alle gleich heissen aber am Schluss nur ne 
andere Zahl haben. (void led1 () - void led10 ())

Jetzt würde es mich interessieren, ob ich im Funktionsaufruf irgendwas 
schreiben kann von wegen void led[x] (); und dann die Variable "x" 
raufzählen kann. Ist sowas möglich?

MFG
Dave

von Düsendieb (Gast)


Lesenswert?

Dave Chappelle schrieb:
> die alle gleich heissen

Die Frage ist aber ob sie innen gleich oder ähnlich sind.

Man kann einer Funktion auch zwei Parameter übergeben.

von Mad (Gast)


Lesenswert?

Definitiv NEIN.

Aber warum nicht die Funktionen nicht zb. so aufrufen:

led_on(led1);

led_off(led2);

usw.

von Dave C. (dave_chappelle)


Lesenswert?

Düsendieb schrieb:
> Die Frage ist aber ob sie innen gleich oder ähnlich sind.
>
> Man kann einer Funktion auch zwei Parameter übergeben.

Ja, die sind ziemlich ähnlich, gleich natürlich nicht, sonst würds nicht 
viel Sinn machen :)

Wie meinst du das?

von Michael R. (dj_motionx)


Lesenswert?

Verwende doch einfach nur eine Funktion led und übergib die Zahl als 
Argument a la led(unsigned int zahl) in der Funktion kannst du dann 
beliebig deinen Programmfluss verzweigen.

L.g.

von Dave C. (dave_chappelle)


Lesenswert?

Ich muss gestehen, ich arbeite noch nicht wirklich lange mit Funktionen.
Bisher musste ich nie über das (void) in den Klammern hinaus, resp. über 
das gar nichts :P
Was bedeutet die Zahl resp. der Wert in der Klammer?

Bitte nicht hauen, ich bin noch am lernen :P

von Lukas v. d. I. (Gast)


Lesenswert?

Hi

weiß ja nicht was du genau vorhast aber du könntest dir evtl mit einer 
weiteren Funktion mit einer switch-case abfrage weiterhelfen die dann je 
nach variablenwert auf die entsprechende LED() funktion verweist...

von Ahmed (Gast)


Lesenswert?

mach einen Array von Funktionsadressen. Dann rufe den jeweiligen Eintrag 
auf.
Da gibts ein Beispiel: 
http://www.java2s.com/Code/C/Function/Arrayoffunctionpointer.htm

von Gerhard P. (gp144) Benutzerseite


Lesenswert?

Du kannst ein Array von Funktionszeigern anlegen.

void led1();
void led2();
..
..


typedef void (*PF)();

PF led_functions[10];       // Array von Funktionszeigern.

led_functions[0] = &led1;   // Array initialisieren
led_functions[1] = &led2;
...



int main()
{

   led_functions[0]();      // Funktion aufrufen via Funktionspointer
   led_functions[1]();

}

Gruss Gerd

von Dave C. (dave_chappelle)


Lesenswert?

Lukas v. d. I. schrieb:
> weiß ja nicht was du genau vorhast aber du könntest dir evtl mit einer
> weiteren Funktion mit einer switch-case abfrage weiterhelfen die dann je
> nach variablenwert auf die entsprechende LED() funktion verweist...

Ja das ist sogar mein Plan :)
Wollte nur beim Case '1' led1 Case '2' led1 + led2 etc..

Ich werde wohl die Funktionen noch etaws umschreiben, dachte vllt. geht 
das wie ich mir das vorgestellt habe mit dem led[x] oder led'x' oder was 
auch immer.

Danke für eure Hilfe

von Johnny B. (johnnyb)


Lesenswert?

Dave Chappelle schrieb:
> void led[x] (); und dann die Variable "x"
> raufzählen kann. Ist sowas möglich?

Im Prinzip ist das schon möglich. Man kann in C ein Array mit 
Funktionspointern anlegen und die dann so änhlich aufrufen, wie Du es 
beschrieben hast.
Für Deine Anwendung macht das aber keinen Sinn.
Du kannst es so lösen, wie es Michael beschreibt; mit einer Funktion, 
bei welcher Du Parameter mitgibst.
Suche mal im Internet mittels Stichworten wie "C", "Funktion", 
"Parameter", ...

von Johannes G. (gutenberg)


Lesenswert?

Was du willst ist bestimmt ganz einfach. Du musst dir aber dringend C 
Grundlagen erarbeiten.

Wahrscheinlich läufts drauf raus dass du einfach einen Parameter 
übergibst, also led(1) bzw. led(7) etc. Du hast also nur eine Funktion 
led(int number)

von Michael R. (dj_motionx)


Lesenswert?

Ahmed schrieb:
> mach einen Array von Funktionsadressen. Dann rufe den jeweiligen Eintrag
> auf.

:-) War auch mein erster Gedanke. ich glaube aber was Dave machen will 
geht auch viel einfacher.

Der Plan mit einer Funktion und dann mit switch -case verzweigen sollte 
dich gut und übersichtlich zum Ziel führen.
Wie Funktionen allgemein verwendet werden kannst du bei Dr.Google oder 
old school in einem C-Buch nachlesen.

L.g.

von Ahmed (Gast)


Lesenswert?

Switch-Case tut. If Else auch. Optimaler sieht es so aus wie bereits 
hingewiesen:

irgendwo oben im Code:
void (*led[4]) (void) = {led0, led1, led2, led3,...};

irgendwo unten:
led[x]();

von Yalu X. (yalu) (Moderator)


Lesenswert?

@Dave:
Poste doch mal den Quellcode deiner Funktionen. Dann verrät dir sicher
jemand die optimale Lösung für deinen konkreten Fall :)

von Johannes G. (gutenberg)


Lesenswert?

Ahmed schrieb:
> Optimaler sieht es so aus wie bereits
> hingewiesen:
>
> irgendwo oben im Code:
> void (*led[4]) (void) = {led0, led1, led2, led3,...};
>
> irgendwo unten:
> led[x]();

Bitte schlagt doch einem Anfänger nicht so seltsame Sachen vor. Wenn man 
so etwas für nötig hält, hat man wahrscheinlich schon konzeptionell 
irgendwas schwer verbockt. Wahrscheinlich will er doch nur LED x 
umschalten oder so was.

von Mad (Gast)


Lesenswert?

Da fragt einer nach einfachen Funktionsaufrufen und ihm wird gleich zu 
Zeigern geraten... traurig.

So etwas mahcht jeder mit einfachen Parametern, in der Funktion dann mit 
case unterscheiden. Fertig.

Und das ist mit Sicherheit übersichtlicher als der Zeiger-Kram...

von Ahmed (Gast)


Lesenswert?

Mad schrieb:
> Da fragt einer nach einfachen Funktionsaufrufen und ihm wird gleich zu
> Zeigern geraten... traurig.

Es gibt unendlich viele Arten, das ganze zu realisieren. Geraten wurde 
ihm zur optimalen Lösung. Das andere "Mad" sind, weil sie kein C können, 
steht hier nicht zur Diskussion.

Wenn der TE damit nichts anfangen kann (nichts gegen dich, Dave), dann 
muss er solange C Tutorials wälzen, bis er etwas damit anfangen kann. 
Oder nicht solche Fragen stellen. Nicht in einem Mikrocontroller-Forum. 
Vielleicht eher in einem C-For-Kids Forum.

von Dave C. (dave_chappelle)


Lesenswert?

Oke ich muss mal kurz was richtigstellen.
Die Übergabe eines Parameters erachte ich als nicht so sinnvoll (ausser 
ich habe da etwas falsch verstanden).
In meinen einzelnen Funktionen werden Pins gesetzt, in allen Funktionen 
verschiedene.

also z.B.
1
void led8 ()
2
{
3
kathode1 = 1;
4
kathode2 = 0;
5
PORTC = 0x00;
6
anode4 =1;
7
}

Das mit dem Array habe ich mir auch überlegt, da wusste ich nur noch 
weniger wie die Syntax aussieht :)

Habe noch nie ein Funktionen-Array benutzt.
Ich weiss aber was ein Array ist und auch was Pointer sind, nur bin ich 
eben erst am Anfang.

Ahmed schrieb:
> Oder nicht solche Fragen stellen. Nicht in einem Mikrocontroller-Forum.
> Vielleicht eher in einem C-For-Kids Forum.

Ich denke mir Experten können auch triviale Fragen beantworten?
Natürlich ist die Frage nicht schwer, wenn man C voll umfänglich 
versteht!

von Ticker (Gast)


Lesenswert?

Dave Chappelle schrieb:
> Ich denke mir Experten können auch triviale Fragen beantworten?
> Natürlich ist die Frage nicht schwer, wenn man C voll umfänglich
> versteht!


Ja. Hab mich nur etwas aufgeregt über: traurig, einen Neuling mit 
Pointern zu verunsichern. Offensichtlich hat der "Neuling" ja schon mal 
Kontakt mit Pointern gehabt. Außerdem kommt man als Programmierer um 
Zeiger nicht herum, dass ist nicht nur ein Thema für "Experten".

Es gibt zwei Lösungswege. Der intuitive über Switch...case...case oder 
das gleiche per If...else...else. Dies erzeugt einen langen Quelltext 
und braucht auch bei der Ausführung viel Zeit, besonders wenn die 
häufigsten Case/Else-Zweige unten stehen.

Die bessere/übersichtlichere Lösung sind die Funktionspointer. 
Eigentlich nicht schwer zu nutzen. Braucht sehr wenige Zeilen Quelltext, 
und die Ausführung ist sehr viel schneller.

Wenn die Größe der Firmware egal ist (weil sowieso sehr klein), dann 
kann man auch Makros nutzen. Aber die Vor- und Nachteile von Funktionen 
vs. Makros sind ja allgemein bekannt. Dafür definiert man oben etwas 
wie:

#define macro_led0() PORTC = 0x00; anode4 =1

und unten im Code sagt man dann

macro_led0();

Hoffe die Diskussion ist hilfreich.

von Dave C. (dave_chappelle)


Lesenswert?

Habe jetzt durch diese Diskussion das eine oder andere gelernt, ja.
Allerdings werde ich nicht um einen Switch kommen, da je nach grösse 
meiner Variable eine bestimmte Funktion aufgerufen werden muss.

Werde das ganze nochmals überdenken, gebe dann Bescheid.

von Ticker (Gast)


Lesenswert?

#include <stdio.h>

//Funktionen, die die LEDs schalten:
void led0(void) {printf("led0\n");}
void led1(void) {printf("led1\n");}
void led2(void) {printf("led2\n");}

//Funktionsarray:
void (*led[3]) (void) = {led0, led1, led2};

//Aufruf im Hauptprogramm:
int main(void) {
led[0]();
led[1]();
led[2]();
}

von Ticker (Gast)


Lesenswert?

...in deinem Fall, ohne Switch:

led[x]();

von Bernd N (Gast)


Lesenswert?

>> Allerdings werde ich nicht um einen Switch kommen, da je nach grösse
>> meiner Variable eine bestimmte Funktion aufgerufen werden muss.

Genau dieser Zusammenhang sollte von dir erklärt werden. So ist es ein 
Ratespiel.

Beispiel: In Abhängigkeit eines AD Wandlerwertes sollen 1-20 LEDs 
geschaltet werden z.B. als Leuchtband (LED Kette). Wenn das Ganze linear 
verläuft dann packt man das in eine Formel und berechnet die Anzahl der 
LEDs und übergibt das an eine einzige Ausgabe welche den Parameter 
(AnzahlLeds) aufnehmen kann.

von Dave C. (dave_chappelle)


Lesenswert?

Ticker schrieb:
> #include <stdio.h>
>
> //Funktionen, die die LEDs schalten:
> void led0(void) {printf("led0\n");}
> void led1(void) {printf("led1\n");}
> void led2(void) {printf("led2\n");}
>
> //Funktionsarray:
> void (*led[3]) (void) = {led0, led1, led2};
>
> //Aufruf im Hauptprogramm:
> int main(void) {
> led[0]();
> led[1]();
> led[2]();
> }

Das klingt gut, das war es, was ich gesucht habe.
Falls schon jemand von dieser Lösung sprach, sorry, habe es wohl nicht 
auf Anhieb verstanden!
Danke für die ausführliche Beschreibung.

von Ticker (Gast)


Lesenswert?

Dave Chappelle schrieb:
> Falls schon jemand von dieser Lösung sprach, sorry, habe es wohl nicht
> auf Anhieb verstanden!

Ja, ich.
Kleiner Scherz. Freut mich wenn du weiter kommst.

von Karl H. (kbuchegg)


Lesenswert?

Oh Mann.

Da hat einer Schwierigkeiten mit Funktionsargumenten und wahrscheinlich 
ist seine Lösung darin zu suchen, dass er sich ganz einfach ein Array 
mit Masken zurechtlegt, welches er über einen Index anspricht und ihr 
ratet ihm zu Funktionspointern.

Seid ihr noch zu retten?

von Karl H. (kbuchegg)


Lesenswert?

Dave Chappelle schrieb:


> Ich denke mir Experten können auch triviale Fragen beantworten?
> Natürlich ist die Frage nicht schwer, wenn man C voll umfänglich
> versteht!


Von vollumfänglich kann überhaupt nicht die Rede sein!
Das sind banalste Grundlagen.
Sozusagen 3. Stunde C Unterricht von 20.

Beschreib endlich dein wirkliches Problem und hör auf eine Lösung zu 
verfolgen, die dich in deiner C Entwicklung nicht weiterbringt.

von Karl H. (kbuchegg)


Lesenswert?

Ahmed schrieb:
> Mad schrieb:
>> Da fragt einer nach einfachen Funktionsaufrufen und ihm wird gleich zu
>> Zeigern geraten... traurig.
>
> Es gibt unendlich viele Arten, das ganze zu realisieren.

Entschuldige aber das ist einfach nur kompletter Blödsinn! Einem 
Anfänger zeigt man nicht die komlpexeste und komplizierteste Art, wie er 
dieses Problem angehen kann. Wenn er in einem Jahr das erste mal auf 
Funktionspointer stösst, dann ist das früh genug. Früher braucht kein 
Mensch Funktionspointer.
Das macht mich richtig wütend, dass du du diesen Unsinn auch noch 
verteidigst.

Er soll seine 8 oder 10 Funktionen herzeigen, dann sieht man mal weiter 
mit welcher Technik man die 10 Funktionen zu einer einzigen 
zusammenfassen kann.

von camikusch (Gast)


Lesenswert?

Dave Chappelle schrieb:
> In meinen einzelnen Funktionen werden Pins gesetzt, in allen Funktionen
> verschiedene.
>
> also z.B.
>
> void led8 ()
> {
> kathode1 = 1;
> kathode2 = 0;
> PORTC = 0x00;
> anode4 =1;
> }

die prozedur sollte also setPins(_param1, ... _paramx) heißen?

solang dir der speicher reicht schreibs so wie es für dich am les- 
debug- und wartbarsten ist :)

von Peter D. (peda)


Lesenswert?

Ich vermute mal, die 10 Funktionen sind nur ein einfacher 7-Segment 
Dekoder.


Peter

von Johannes G. (gutenberg)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Oh Mann.
>
> Da hat einer Schwierigkeiten mit Funktionsargumenten und wahrscheinlich
> ist seine Lösung darin zu suchen, dass er sich ganz einfach ein Array
> mit Masken zurechtlegt, welches er über einen Index anspricht und ihr
> ratet ihm zu Funktionspointern.
>
> Seid ihr noch zu retten?

+1k

Dave, in deinem eigenen Interesse, ignorier den Müll mit Pointern hier. 
Du musst daran arbeiten das was du programmieren willst in eine 
möglichst einfache Logik zu verpacken (das ist quasi die Vorarbeit die 
du leisten musst) und dann schreibt sich das in C auch ganz einfach.

Wahrscheinlich kannst du ein Array machen wo all deine "Schalter" drin 
sind für jede LED, also der Zustand von kathode1, kathode2, anode4, 
portc und allen anderen. Dann rufst du deine Funktion auf mit 
led_schalten(i), und in der Funktion selber setzt du all die variablen 
(kathode, port etc.) auf den wert im array mit index i.

von Lötspitze (Gast)


Lesenswert?

Mad schrieb:
> Definitiv NEIN.
>

Doch, das ganze nennt man Funktionszeiger.

http://www.mbernstein.de/atari/prog/kurse/c-kurs/0a08.htm


Ticker schrieb:
> Es gibt zwei Lösungswege. Der intuitive über Switch...case...case oder
> das gleiche per If...else...else. Dies erzeugt einen langen Quelltext
> und braucht auch bei der Ausführung viel Zeit, besonders wenn die
> häufigsten Case/Else-Zweige unten stehen.

Wenn die Frage, welche Funktion aufgerufen werden soll, in der 
Aufrufenden Funktion abgefragt wird, ist hier mit Funktionszeigern nicht 
viel gewonnen.
In diesem Fall ist die Switch/Case Anweisung sinnvoller, da sie zu 
besserem wartbarerem Code führt.

Es hängt halt ganz vom Code ab.
Wenn in der aufrufenden Funktion sowieso eine Abfrage enthalten ist und 
dort z.B. mehrere Dinge ausgeführt werden, dann können die 
Funktionszeiger durchaus Sinn machen.



Ansonsten sind Switch/Case Anweisungen verglichen mit mehreren If/Else 
Abfragen sehr effizient. Wenn möglich sollte man eine Switch Anweisung 
einem If/Else Block immer vorziehen.

von Lötspitze (Gast)


Lesenswert?

Dave Chappelle schrieb:
> Lukas v. d. I. schrieb:
>> weiß ja nicht was du genau vorhast aber du könntest dir evtl mit einer
>> weiteren Funktion mit einer switch-case abfrage weiterhelfen die dann je
>> nach variablenwert auf die entsprechende LED() funktion verweist...
>
> Ja das ist sogar mein Plan :)
> Wollte nur beim Case '1' led1 Case '2' led1 + led2 etc..
>

Kann man zwar machen, aber eine extra Funktion, die nur schaut, welche 
Funktion aufgerufen werden soll, führt zu mindestens einem überflüssigen 
Funktionsaufruf.

Das ist also langsamer als eine Funktion, die für alle LEDs da ist.

von Lötspitze (Gast)


Lesenswert?

Johannes G. schrieb:

> Wahrscheinlich kannst du ein Array machen wo all deine "Schalter" drin
> sind für jede LED, also der Zustand von kathode1, kathode2, anode4,
> portc und allen anderen. Dann rufst du deine Funktion auf mit
> led_schalten(i), und in der Funktion selber setzt du all die variablen
> (kathode, port etc.) auf den wert im array mit index i.

Ich würde das ganze einfach in ein Struct packen und vom Struct dann ein 
Array anlegen.

struct leds{
  bool kathode1;
  bool kathode2;
  bool anode4;
  int portc;
}

struct leds x[5];


Und dann die jeweiligen x Einträge einmalig initialisieren. (das kann 
auch in einer extra Init Funktion geschehen.
x[0].kathode1 = 0;
...
x[0].portc = 0x00;

...
x[5].kathode1 = 1;
...
x[5].portc = 0x00;


Anschließend einfach eine Funktion setLed(leds x) aufrufen, die das 
jeweilige Struct als Parameter aufnimmt.

Aufgruf geht dann mit
setLed(*x[4]);


Siehe auch:
http://en.wikipedia.org/wiki/Struct_%28C_programming_language%29

von Ahmed (Gast)


Lesenswert?

Moderatoren zensieren hier unliebsame Aussagen. Ich mag sie nicht 
besonders.

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


Lesenswert?

Ahmed schrieb:
> Moderatoren zensieren hier unliebsame Aussagen.

Moderatoren löschen Beleidigungen und Unterstellungen — und dies ist
unsere Aufgabe.  Außerdem mögen Moderatoren Trolle nicht besonders.

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.