Moin!
Frage vorweg: wie heisst das, was man durch ein #define definiert?
Frage hinterher: ich habe am Atmega einen Demux angeschlossen, der 3
Adress-Eingänge besitzt, welche an den Atmega-Ports hängen.
A0 A1 A2 Y
0 0 0 0
1 0 0 1
0 1 0 2
1 1 0 3
0 0 1 4
Nun möchte ich gern durch ein einfaches
#define dmux_input_(0-4)
machen, dass die entsprechende Bitmaske gesetzt wird. Ich kenne aber nur
Maskierungen, bei denen gleichzeitig ein oder mehrere Bits gesetzt (bzw.
gelöscht) werden, nicht aber gesetzt UND gelöscht.
Wie tut Mann das?
Stephan R. schrieb:> ... bei denen gleichzeitig ein oder mehrere Bits gesetzt (bzw. gelöscht) ...
Dann mach das doch:
#define SET_MUX(x) do { PORTX=(PORTX & ~0x07)|(x) } while (0)
und falls es ohne klammer gehen soll:
#define SET_MUX_1 SET_MUX(1)
Stephan R. schrieb:> Frage vorweg: wie heisst das, was man durch ein #define definiert?
"Makro". ist eine reine Text-Ersetzung, die noch VOR dem Kompilieren
ausgeführt wird.
Stephan R. schrieb:> Dacht ich auch zuerst, aber der restliche Port wird auch verwendet, es> dürfen also nur PORTC0 bis PORTC3 verändert werden.
Genau das macht das Makro doch.
Zuerst wird 0x07 invertiert, ergibt eine Bitmaske 0b11111000.
der PORTC-Zustand wird damit ver-UND-et, d.H. alle bits bis auf die
untersten drei bleiben wie sie sind.
Danach wird der Makro-Parameter dazu ver-ODER-t, es werden also
zusätzlich wieder bits gesetzt.
Solange X keine bits anfasst, die es nicht darf, bleibt der Rest von
PORTC also unverändert.
Wenn du dir selbst nicht traust, kann das Makro das auch erzwingen:
1
#define SET_MUX(x) do { PORTX=(PORTX & ~0x07)|((x) & 0x07); } while (0)
Das ist grad mal harter Tobak für mich! Ich hatte mich (gerade aus dem
Bascom-Lager kommend) schön an die
PORTC |= (1 << PC2)
Schreibweise gewöhnt.
Ich verstehe die Funktion der (x)- Klammer nicht. Steht die nur zur
Anschauung da oder kann ich die ins Programm übernehmen?
Stephan R. schrieb:> Ich verstehe die Funktion der (x)- Klammer nicht. Steht die nur zur> Anschauung da oder kann ich die ins Programm übernehmen?
Das ist ein Parameter.
Wenn du im Programm später
Okay, das leuchtet ein, ist halt ne "normale" Funktion. Braucht die denn
auch einen Prototypen?
Noch was: mein Compiler (Programmers Notepad) formatiert das Makro nicht
farbig wie in deinem Beispiel sondern nur braun. Warum des?
Stephan R. schrieb:> Okay, das leuchtet ein, ist halt ne "normale" Funktion. Braucht die denn> auch einen Prototypen?
Das ist ein Irrtum. Es sieht nur so aus.
Lies nochmal, was Ernst B* oben schrieb (Textersatz).
Jockel
Stephan R. schrieb:> Okay, das leuchtet ein, ist halt ne "normale" Funktion. Braucht die denn> auch einen Prototypen?
Du brauchst ganz, ganz, ganz dringend ein C-Buch.
Das anlassbedingte Zusammentragen von Halbwissen in einem Forum
funktioniert einfach nicht, wenn man eine Programmiersprache wie C
lernen will.
Verwirrter schrieb:> Gibt es einen Grund dafür das Ganze in eine "Schleife" zu packen, warum> reicht nicht nur die Zuweisung ?
in dem Fall würde es ohne das "while"-Konstrukt auch gehen.
bei "#define ABC(x) a=(x); b=(x)+2" z.B
gäbe es aber ein Problem bei Verwendungen wie:
if (a==23) ABC(42);
(Textersetzung mal von Hand durchführen, wenn das Problem nicht
offensichtlich ist)
durch das "do-while"-Konstrukt wird das umgangen.
Preprozessor-Makros sind da immer etwas eigen. Anfängern würde ich
vorschlagen davon ganz die Finger zu lassen, und normale C-Funktionen zu
verwenden. Wenn man die "Verstanden" hat, kann man sich immer noch
Makros zur "Optimierung" erlernen.
Stephan R. schrieb:> Noch was: mein Compiler (Programmers Notepad) formatiert das Makro nicht> farbig wie in deinem Beispiel sondern nur braun. Warum des?
Das nennt sich Syntax-Highlighting und die Farben sind in jedem Editor
entweder anders oder einstellbar...
Karl heinz Buchegger schrieb:> Das anlassbedingte Zusammentragen von Halbwissen
Oder auch learning by doing find ich eigentlich ganz praktisch. Was ich
nicht brauch, verlern ich gern schnell wieder.
Karl heinz Buchegger schrieb:> Du brauchst ganz, ganz, ganz dringend ein C-Buch.
Da hinten in der Schublade liegt´s! DUCK UND WEG
Danke mit so etwas hatte ich gerechnet,
bei manchen Compilern kann man das auch einfach in geschweifte Klammern
{ .... } packen. Solche kleineren Blöcke stören dann nicht weiter.
Zumindest solange man keine, dadurch lokalen, Variablen anlegt.
(Ex-)Verwirrter schrieb:> Danke mit so etwas hatte ich gerechnet,> bei manchen Compilern kann man das auch einfach in geschweifte Klammern> { .... } packen. Solche kleineren Blöcke stören dann nicht weiter.> Zumindest solange man keine, dadurch lokalen, Variablen anlegt.
Nicht immer: ;)
1
#define TEST(X) do { printf("%d\n",(X)); } while(0)
2
3
if(x)
4
TEST(x);
5
else
6
TEST(x+x);
funktioniert,
1
#define TEST(X) { printf("%d\n",(X)); }
2
3
if(x)
4
TEST(x);
5
else
6
TEST(x+x);
Gibt nen Compiler-Fehler:
> »else« ohne vorheriges »if«
Stephan R. schrieb:> Karl heinz Buchegger schrieb:>> Das anlassbedingte Zusammentragen von Halbwissen>> Oder auch learning by doing find ich eigentlich ganz praktisch. Was ich> nicht brauch, verlern ich gern schnell wieder.
Dazu musst du es aber erst einmal gelernt haben.
Und gerade in C gibt es Unmengen an Fallen und 'Insider-Wissen', ohne
das man nicht weit kommt.
Und mit Verlaub: So toll ist deine C-Performance nicht. Sie zeigt
eigentlich genau das Übliche, was man von einem Foren-Zusammenklauber
erwarten würde: Er kann von allem ein bischen was, aber nichts richtig
und manchmal einfach nur grundfalsch. Und da red ich noch nicht einmal
von den wirklich komplizierten Dingen.
Das stimmt natürlich- wenn man denn den Anspruch hat, C professionell zu
beherrschen.
Das Gute für mich daran: ich brauch mir nicht meine Brötchen damit
verdienen sondern will nur ein kleines Uböötchen damit auslaufen lassen.
Aber in der Aussicht, vielleicht mal in die Programmiererriege "meiner"
Firma aufzurutschen, beleg ich nu ein, zwei Semsester lang
"Programmieren". Vielleicht kann ich ja noch was lernen...
Ernst:
> Wenn du im Programm später> SET_MUX(42);> schreibst, sieht der Compiler:> do { PORTX=(PORTX & ~0x07)|((42) & 0x07); } while (0);> und macht Das Richtige™
Nö, stimmt nicht ganz. er sieht um die 42 keine Klammern, die müsstest
(und sollst) Du im Define angeben.
Probier mal aus:
#define QUAD1(x) (x*x)
#define QUAD2(x) ((x)*(x))
das ist zwar auf den ersten Blick das selbe, aber beim Aufruf von z.B.
QUAD(6 & 6);
kommt für QUAD1 4 heraus und für QUAD2 36, denn der Compiler sieht bei
QUAD1 (6 & 6 * 6 & 6)
eben keine Klammern und rechnet 6 & (6*6) & 6 , weil & eine kleinere
Hierarchiestufe als * hat.
Typische C-Falle, auf die in jedem guten C-Buch hingewiesen wird.
schau genau schrieb:> Probier mal aus:> #define QUAD1(x) (x*x)> #define QUAD2(x) ((x)*(x))>> das ist zwar auf den ersten Blick das selbe, aber beim Aufruf von z.B.> QUAD(6 & 6);
....
Genauso bei
QUAD( 6 + 1 );
(da ist es vielleicht offensichtlicher und im Kopf leichter zu verfolgen
als mit einem binären und)
Beliebt sind auch
i = 7;
j = QUAD( i++ )
(welchen Wert hat i nach der Operation und was ist das Ergebnis? Ist die
Operation überhaupt definiert? Wenn ja: warum? Wenn nein: warum nicht?)
> Typische C-Falle, auf die in jedem guten C-Buch hingewiesen wird.
Ganz genau
Dazu muss man aber erst einmal verinnerlicht haben, dass Makros einfach
nur Textersetzung machen und nicht mehr. Aber auch das steht im besagten
Buch. Zusammen mit ein paar Beispielen, die zeigen wie sich das auswirkt
und was da im Präprozessor wirklich passiert.
Stephan R. schrieb:> Das stimmt natürlich- wenn man denn den Anspruch hat, C professionell zu> beherrschen.
Eben nicht
Ohne einen gewissen Grundstock kannst du auch als Amateur nicht sinnvoll
programmieren.
Von dem was dir jetzt kompliziert vorkommt, bis zu dem, was von einem
Profi selbstverständlich erwartet und verlangt wird, ist noch ein
weiter, weiter Weg. Da passt noch viel dazwischen.
Egal ob du Amateur oder Profi- Radrennfahrer bist, Gleichgewicht halten
müssen beide können. Und man kann sich bei einem Sturz nicht darauf
rausreden, dass man eben kein Profi sei.
schau genau schrieb:> Ernst:>> Wenn du im Programm später>>> SET_MUX(42);>>> schreibst, sieht der Compiler:>>> do { PORTX=(PORTX & ~0x07)|((42) & 0x07); } while (0);>>> und macht Das Richtige™>>> Nö, stimmt nicht ganz. er sieht um die 42 keine Klammern, die müsstest> (und sollst) Du im Define angeben.
in dem Satz fehlt das "und hast" ...
mein #define hat die extra-Klammerung um das "x", also selber "genau
schau"en ;)