Moin
Ich möchte Änderungen an einem ATmega-Port per "griffigem" Unterprogramm
Namen machen, statt das krytisch im Programm.
So hatte ich mir das gedacht:
1
voidBacklight_an(void){PORTD|=(1<<PD4);}// Port PD4 high
2
voidBacklight_aus(void){PORTD&=~(1<<PD4);}// Port PD4 low
3
voidBacklight_wechsel(void){PORTD^=(1<<PD4);}// Port PD4 high<>low
Aber wenn ich im Programm die Zeilen aufrufe
1
Backlight_an;
passiert nichts. Trage ich dagegen im Programm die Zeile
1
PORTD|=(1<<PD4);
ein, dann funktionierts.
Wo liegt mein Fehler? Es soll doch nur das jeweilige Unterprogramm
aufgerufen werden und dort die Zuweisung zum Port-D angepaßt werden, das
kann doch nicht so schwierig sein...
Gruß
Michael
>passiert nichts.
Was heisst das? Gibt es Compilerfehlermeldungen?
Deine Codestücke sind schon syntaktisch nicht korrekt und sollten eine
Fehlermeldung geben. Bitte lies ein C-Buch.
Eine Funktion wie die gezeigte muss mit:
1
Backlight_an();
aufgerufen werden.
Wenn auch bedeutend und im Widersruch zu Deiner Beschreibung ist
andererseits auch nur diese Kleinigkeit falsch.
Kali schrieb:> Deine Codestücke sind schon syntaktisch nicht korrekt und sollten eine> Fehlermeldung geben.
Doch, sind sie.
Aber eine Warnung "statement without effect" sollte eigentlich kommen.
@ Stefan Ernst
>> Deine Codestücke sind schon syntaktisch nicht korrekt und sollten eine>> Fehlermeldung geben.>Doch, sind sie.
Nein. Mit dieser Syntax ist kein Funktionsaufruf ausgedrückt.
Kurz mal vor dem schreiben, denken!
Kali schrieb:> @ Stefan Ernst>>>> Deine Codestücke sind schon syntaktisch nicht korrekt und sollten eine>>> Fehlermeldung geben.>>>Doch, sind sie.>> Nein. Mit dieser Syntax ist kein Funktionsaufruf ausgedrückt.
Dann ist sie semantisch nicht korrekt. Syntaktisch ist es perfektes C.
> Kurz mal vor dem schreiben, denken!
Michael schrieb:> Backlight_an;
Das ist kein Funktionsaufruf. Der Comnpiler sollte dir etwas zu dieser
Zeile mitgeteilt haben.
Backlight_an(); müsste es heißen
Gruß Skriptkiddy
Kali schrieb:> Nein. Mit dieser Syntax ist kein Funktionsaufruf ausgedrückt.
Hab ich ja auch gar nicht behauptet.
Es ist aber eine syntaktisch korrekte Zeile (macht nur nicht das
beabsichtigte), damit ist dein
> syntaktisch nicht korrekt und sollten eine> Fehlermeldung geben.
falsch.
Kali schrieb:> Kurz mal vor dem schreiben, denken!
Dito.
@ Stefan Ernst
>Hab ich ja auch gar nicht behauptet.
Hast Du wohl. Die Ausgangsfrage war ja, warum eine Funktion nicht
ausgeführt wird, obwohl der TO annahm, dass er syntaktisch korrekt einen
Aufruf formuliert hat. Das aber hast er nicht getan.
Der Knackpunkt ist hier, das einer bestimmten Zeichenfolge (Syntax) eine
bestimmte Bedeutung (in diesem Sinne also Semantik) unterstellt wurde.
Eine nicht so zu deutende Formulierung ist syntaktisch nicht korrekt,
denn sie kann nicht wie beabsichtigt gedeutet werden. Sie hat eine
andere Bedeutung.
Kali schrieb:> @ Stefan Ernst>>>> Deine Codestücke sind schon syntaktisch nicht korrekt und sollten eine>>> Fehlermeldung geben.>>>Doch, sind sie.>> Nein. Mit dieser Syntax ist kein Funktionsaufruf ausgedrückt.
"Syntaktisch korrekt" und "Funktionsaufruf findet statt" sind zwei
Aussagen, die nicht besonders viel gemeinsam haben.
Es kann durchaus syntaktisch korrekt sein, und trotzdem kein Aufruf
stattfinden.
Genau das ist hier der Fall.
Kali schrieb:> Der Knackpunkt ist hier, das einer bestimmten Zeichenfolge (Syntax) eine> bestimmte Bedeutung (in diesem Sinne also Semantik) unterstellt wurde.> Eine nicht so zu deutende Formulierung ist syntaktisch nicht korrekt,> denn sie kann nicht wie beabsichtigt gedeutet werden. Sie hat eine> andere Bedeutung.
?
Eine andere (Be-) Deutung ist doch eben nicht Syntax, sondern Semantik.
@ Klaus Wachtler
>> Nein. Mit dieser Syntax ist kein Funktionsaufruf ausgedrückt.>"Syntaktisch korrekt" und "Funktionsaufruf findet statt" sind zwei
Aussagen, die nicht besonders viel gemeinsam haben.
Nun, Du hast das vielleicht anders gemeint: Genau genommen, sind auch
"Funktionsaufruf ausgedrückt" und "Funktionsaufruf findet statt" zwei
verschiedene Dinge.
"Syntaktisch korrekt" und "Funktionsaufruf ausgedrückt" haben da schon
eher etwas gemeinsam.
Ich denke, schon dadurch, dass oben drüber steht "Syntax eines
C-Programmes", enthält die Beschreibung dieser Syntax eine Bedeutung.
Dies kann man herunter auf jeden Ausdruck anwenden der für sich genommen
eine Bedeutung hat. D.h. es gibt Zeichenfolgen, die einen
Funktionsaufruf ausdrücken und solche die das nicht tun.
Das führt zu dem weiteren Gedanken, das so etwas wie eine "reine Syntax"
in diesem Zusammenhang nicht existiert.
Kali schrieb:> Der Knackpunkt ist hier, das einer bestimmten Zeichenfolge (Syntax) eine> bestimmte Bedeutung (in diesem Sinne also Semantik) unterstellt wurde.> Eine nicht so zu deutende Formulierung ist syntaktisch nicht korrekt,> denn sie kann nicht wie beabsichtigt gedeutet werden. Sie hat eine> andere Bedeutung.
Interessanter Versuch, sich rauszuwinden. ;-)
Jetzt finde ich es aber sehr spannend von dir zu erfahren, wie du da nun
auch noch das "sollten eine Fehlermeldung geben" mit einbaust.
>Eine andere (Be-) Deutung ist doch eben nicht Syntax, sondern Semantik.
Ich meine, das schon in der Syntax eine Deutung enthalten ist.
Es scheint mir, als wenn allein die Tatsache, das es keine alternative
Syntax für einen Funktionsaufruf gibt, darauf hindeutet, das man die
Syntax nicht losgelöst von der Bedeutung betrachten kann. (Insofern ist
C allerdings ein zwar häufiger aber ein Sonderfall).
Das man als Compilerbauer konstruktiv die Syntaxerkennung von der
Übersetzung trennt ist nicht so aufzufassen, das dies auch "tatsächlich"
eine Unabhängigkeit von Syntax und Semantik bedeutet.
@ Stefan Ernst
>Interessanter Versuch, sich rauszuwinden. ;-)
Danke. ;-)
>Jetzt finde ich es aber sehr spannend von dir zu erfahren, wie du da nun>auch noch das "sollten eine Fehlermeldung geben" mit einbaust.
Da hast Du mich jetzt erwischt. Es ist zwar völlig willkürlich ob man
solch einen Fall nun als Fehler oder als eine warnwürdige Situation
auffasst. Auch für letzteres gibt es sicherlich Argumente. Aber auch
nach meiner Kenntnis würde das bei den Compilern die ich kenne, eine
Warnung geben.
Kali schrieb:> Ich meine, das schon in der Syntax eine Deutung enthalten ist.
Ob sie enthalten ist oder daneben steht, ist jetzt vielleicht etwas
philosophisch.
Aber in jedem Fall heißt der Teil mit der Bedeutung dann "Semantik",
und nicht mehr "Syntax".
---
Warum erinnert mich diese Argumentation an meinen Bruder?
Der hat mich bei einer unser diversen Auseinandersetzungen mal ins Bein
gebissen.
Vor den Eltern mit dem Zahnabdruck konfrontiert, war seine Ausrede: er
hätte gerade zufällig gegähnt, ich wäre ihm reingelaufen.
@ Klaus Wachtler
>Ob sie enthalten ist oder daneben steht, ist jetzt vielleicht etwas>philosophisch.
Da stimme ich zu. Ohnehin, ist nach "den Regeln des Handwerks" die Sache
klar. Ein Parser würde den Code des TO als syntaktisch korrekt erkennen.
(Das als auch Antwort auf Deinen Vergleich mit Deinem Bruder). Meine
Einlassung, das es sich syntaktisch nicht um einen Funktionsaufruf
handelt, ist demnach die nachträgliche Rechtfertigung meiner unklaren
Formulierung.
Interessant finde ich das aber schon: Diese Trennung von Syntax und
Semantik ist eigentlich erstmal nur eine rein konstruktive (beim Bau
eines Compilers). Aber "philosophisch" betrachtet ist diese Trennung
nicht vorhanden. Mein Beispiel: "... , das es keine alternative
Syntax für einen Funktionsaufruf gibt," scheint mir dafür ein Beleg zu
sein.
Denn wenn es keine alternative Syntax dafür gibt, so hat dieser Teil der
Syntax auch eine "Bedeutung".
Kali schrieb:> Aber "philosophisch" betrachtet ist diese Trennung> nicht vorhanden. Mein Beispiel: "... , das es keine alternative> Syntax für einen Funktionsaufruf gibt," scheint mir dafür ein Beleg zu> sein.
Die Syntax hat mit einem Funktionsaufruf nichts zu tun.
Bei der Syntax geht es darum, wie man Zeichen kombinieren kann.
Ob sich daraus ein Sinn ergibt, und wenn ja welcher, hat dann nichts
mehr mit Syntax zu tun.
Bei C konkret geht es bei Syntax darum, welche Zeichenfolgen zulässig
sind und wie sie zu Token zusammengefasst werden.
Erst wenn die Token (z.B. ein Name anstatt Zeichenfolgen, oder Klammern
nicht mehr als Zeichen, sondern als Symbol) auf dem Tisch liegen, wird
überlegt, ob der Name für eine Variable steht, eine Funktion etc, und ob
die Klammern zu einem Rechenausdruck gehören, zu einem Cast, zu einer
Funktionsdeklaration, einem Funktionsaufruf, oder ob sie völliger
Blödsinn sind.
Das hat aber dann schon nichts mehr mit Syntax zu tun.
Aus http://de.wikipedia.org/wiki/Syntax:
> Unter der Syntax einer formalen Sprache (formale Syntax)> – wie etwa Programmiersprachen in der Informatik oder> Kalküle in der Logik – versteht man ein System von Regeln,> nach denen erlaubte Konstruktionen bzw. wohlgeformte Ausdrücke> aus einem grundlegenden Zeichenvorrat (dem Alphabet) gebildet> werden[6] – wobei von der inhaltlichen Bedeutung der Zeichen>> abgesehen wird bzw. werden kann.
Ansonsten wäre ja die Semantik arbeitslos.
>> Aber "philosophisch" betrachtet ist diese Trennung>> nicht vorhanden. Mein Beispiel: "... , das es keine alternative>> Syntax für einen Funktionsaufruf gibt," scheint mir dafür ein Beleg zu>> sein.>Die Syntax hat mit einem Funktionsaufruf nichts zu tun.>Bei der Syntax geht es darum, wie man Zeichen kombinieren kann.
Dem kann ich zustimmen. Ich wollte nicht sagen, das man aus der
Darstellung der Syntax alleine auf die Semantik schliessen kann, dass
also meine Aussage: 'Aber "philosophisch" betrachtet ist diese Trennung
nicht vorhanden.' einfach nur seine Umkehrung, d.h. dass die Semantik
aus der Syntax ableitbar ist, bedeuten soll. Das ist sicherlich nicht
richtig.
Es geht mir darum, das zwischen Syntax und Semantik gewisse
Wechselbeziehungen bestehen.
>Ob sich daraus ein Sinn ergibt, und wenn ja welcher, hat dann nichts>mehr mit Syntax zu tun.
Man spezifiziert doch eine Syntax mit einer bestimmten Absicht. Diese
Absicht bezieht sich auf die Menge der Bedeutungen die man mit
Ausdrücken die der Syntax entsprechen, mitteilen können will.
Wenn ich z.B. einem Namen, zwei verschiedene Bedeutungen geben will muss
ich in der Syntax einen Unterschied einbauen, so das seine Bedeutungen
unterscheidbar sind, was aber nicht gleichbedeutend damit ist, dass die
Bedeutung inhaltlich aus diesem Unterschied ableitbar ist.
Dein Satz:
>Die Syntax hat mit einem Funktionsaufruf nichts zu tun.
ist so gesehen, nicht vollständig korrekt.
Die Syntax sagt zwar nichts darüber aus, ob ein Name nun als
Funktionsaufruf oder als ein Zeiger auf die Funktion zu verstehen ist.
Aber es muss einen Unterschied im Kontext geben, damit man das eine vom
anderen unterscheiden kann.
Insofern (und in anderer Hinsicht) wirkt sich die Semantik auf die
Syntax aus.
Kali schrieb:> Dein Satz:>>Die Syntax hat mit einem Funktionsaufruf nichts zu tun.> ist so gesehen, nicht vollständig korrekt.
Aber nur so gesehen; richtig gesehen ist mein Satz korrekt :-)
> Die Syntax sagt zwar nichts darüber aus, ob ein Name nun als> Funktionsaufruf oder als ein Zeiger auf die Funktion zu verstehen ist.> Aber es muss einen Unterschied im Kontext geben, damit man das eine vom> anderen unterscheiden kann.
Man könnte eineSprache so konstruieren, daß man einem Namen ansieht,
wozu er gut ist.
In C ist das aber nicht so.
Natürlich sollte sich aus dem Kontext ergeben, was gemeint ist.
Bei C aber eben nicht aus der Syntax, sondern erst aus der Semantik.
Du kannst dich winden wie du willst, aber die Syntax hat nichts mit der
Bedeutung der Token zu tun.
Ewiges Leugnen ändert auch nichts an den Tatsachen, und einen C-Compiler
kannst du auch nicht mit endlosen Debatten zum Übersetzen bewegen.
Magst du nicht einfach mal nachlesen, was Syntax ist? Das würde
vielleicht die Diskussion etwas erleichtern.
Kali schrieb:> Es geht mir darum, das zwischen Syntax und Semantik gewisse> Wechselbeziehungen bestehen.
Warum nicht?
Das ist doch lange kein Grund, die beiden zu vermischen.
>Natürlich sollte sich aus dem Kontext ergeben, was gemeint ist.>Bei C aber eben nicht aus der Syntax, sondern erst aus der Semantik.
Das habe ich auch garnicht behauptet.
Ich schrieb z.B.
>Die Syntax sagt zwar nichts darüber aus, ob ein Name nun als>Funktionsaufruf oder als ein Zeiger auf die Funktion zu verstehen ist.>Ewiges Leugnen ändert auch nichts an den Tatsachen, und einen C-Compiler>kannst du auch nicht mit endlosen Debatten zum Übersetzen bewegen.>Magst du nicht einfach mal nachlesen, was Syntax ist?
Hm. Wieso leugnen? Was leugnen? Keine Ahnung was Du da in den falschen
Hals bekommen hast. Schade.
Seltsam. Was soll auf einmal dieser Tonfall?
Abgesehen davon:
>Natürlich sollte sich aus dem Kontext ergeben, was gemeint ist.
ist der Kontext Teil der Syntax.
Na gut. Wirklich schade.
Michael schrieb:> Ja das wars. Danke
Es funktioniert zwar, aber du bist auf dem besten Weg, dir einen
grauenhaften Programmierstil anzugewöhnen.
Deswegen:
Kali schrieb:> Bitte lies ein C-Buch.
Und zwar von Anfang an. Wenn das Kapitel mit den Pointern kommt, kannst
du es erstmal beiseite legen, aber bis dahin arbeite das gewissenhaft
durch.
Michael schrieb:> Unterprogramm
In C gibt es keine Unterprogramme!
Sowas macht man nicht:
Michael schrieb:> void Backlight_an(void) { PORTD |= (1<<PD4); }
Dafür nimmt man Makros:
Martin schrieb:> Beispielsweise#define Backlight_an PORTD|=_BV(PD4)
Wobei diese Art schon etwas obsolet ist.
#define Backlight_an PORTD |= (1<<PD4)
ist die modernere Schreibweise.
Wenn man das schon in eine Funktion packen will, dann macht man das mit
EINER und nicht mit drei Funktionen:
void Backlight(char function)
{
switch (function)
{
case 0:
PORTD &= ~(1<<PD4);
break;
case 1:
PORTD |= (1<<PD4);
break;
case 2:
PORTD ^= (1<<PD4);
break;
}
}
Die drei Zustände kannst du dann noch "griffig" definieren
#define OFF 0
#define ON 1
#define TOGGLE 2
Und dann: Backlight(ON);
mfg.
>> Beispielsweise#define Backlight_an PORTD|=_BV(PD4)>Wobei diese Art schon etwas obsolet ist.>#define Backlight_an PORTD |= (1<<PD4)>ist die modernere Schreibweise.
Da soll mir aber einer erklären, was an letzterer Schreibweise
"moderner" ist. _BV ist ein Makro, welches man wunderbar einsetzen kann
und laut offizieller Stelle (avr-libc Dokumentation) auch nicht
"obsolet" ist...
> Oder man markiert die Funktion als inline...
Was aber nur genau so wie das Makro funktioniert, wenn man zusätzlich
noch das passende (vom Compiler abhängige) Attribut hinzugibt, ansonsten
ist inline nämlich nur ein Vorschlag an den Compiler. Ob er es
letztenendes auch macht, ist seine Sache.
Dominik Honnef schrieb:> Da soll mir aber einer erklären, was an letzterer Schreibweise> "moderner" ist. _BV ist ein Makro, welches man wunderbar einsetzen kann> und laut offizieller Stelle (avr-libc Dokumentation) auch nicht> "obsolet" ist...
#define _BV(bit) (1 << (bit))
Mit obsolet und modern lag ich vielleicht etwas daneben.
Nichtdestotrotz wird in den Datenblättern die (1 << xx) -Schreibweise
verwendet. Genauso wie im AVR-GCC-Tutorial.
Ob man es nun so macht oder das _BV -Makro verwendet ist natürlich auch
Geschmackssache und jedem selbst überlassen. Ich hatte jetzt nicht vor,
jemandem auf den Schlips zu treten.
Allerdings wird sich ein Anfänger beim Anblick desselben nur die Haare
raufen, weil er überhaupt nicht weiß, was das soll.
(1 << xx) begegnet einem dagegen andauernd.
Aber das muß man jetzt nicht in den folgenden 27 Posts durchdiskutieren.
mfg.
Thomas Eckmann schrieb:> Wenn man das schon in eine Funktion packen will, dann macht man das mit> EINER und nicht mit drei Funktionen:>> void Backlight(char function)> {> switch (function)> {> case 0:> PORTD &= ~(1<<PD4);> break;>> [...]> }> }>> Die drei Zustände kannst du dann noch "griffig" definieren>> #define OFF 0> #define ON 1> #define TOGGLE 2>> Und dann: Backlight(ON);
Danke für den Hinweis. Ich nehme das auf und werde es künftig so
umsetzen.
Gruß
Michael
Bevor du es zu sehr verinnerlichst: statt der #define könnte man auch
eine enum nehmen.
Viele Menschen (so auch ich) würden das bevorzugen.
Je weniger Makros, umso besser.