Gast
#652816
Hallo zusammen, kann mir bitte mal jemand genau die folgende Anweisung bit für bit erklären. while (!(UCSR1A & (1<<UDRE1))) Blick das mit den Opreatoren noch nicht so ganz... :-(
|
Anzeige
|
Komm mit der while Anweisung net klar
Gast
#652816
Hallo zusammen, kann mir bitte mal jemand genau die folgende Anweisung bit für bit erklären. while (!(UCSR1A & (1<<UDRE1))) Blick das mit den Opreatoren noch nicht so ganz... :-( Der Inhalt der Schleife wird ausgeführt, solange die bitweise UND-Verknüpfung des Registers UCSR1A mit dem Ausdruck (1 << UDRE) nicht wahr ist.
Gast
#652826
Ich blick das nicht ganz, weil UCSR1A ist ja ein ganzes Register, also 8 bit. bsp. 00100000 Wenn wir mal annehmen das die 1 UDRE1 ist jetz verunde ich zusätzlich noch UDRE damit??? Was kommt dann in diesem bsp raus?? UDRE ist ein Makro, das in der Header-Datei definiert ist. Wenn UDRE das Bit mit der Nummer 1 ist, dann steht in der Header-Datei
Wenn man jetzt eine "1" (binär 00000001) um "UDRE" Stellen (also um eine Stelle) nach links schiebt, dann erhält man 00000010. Und damit wird das UCSR1A jetzt verknüpft. Der Rest steht in jedem C-Buch und -Tutorial. EDIT: Sorry, muss natürlich "UDRE1" heißen und nicht "UDRE"...
Gast
#652838
Es wird hier UCSR1A mit einer um den Wert von UDRE1 nach links geschobenen "1" verundet. UDRE1 wird irgendwo in einem Header als Zahl zwischen 0..7 definiert sein. Also als das n-te Bit. 1 << 0 = 1 1 << 1 = 2 1 << 2 = 4 1 << 3 = 8 usw. 1 << UDRE1 = ? Klar? >kann mir bitte mal jemand genau die folgende Anweisung bit für bit >erklären. >while (!(UCSR1A & (1<<UDRE1))) >Blick das mit den Opreatoren noch nicht so ganz... :-( entweder ein Wert von 0 oder 00100000. Durch die UND Maske kann es nur diese 2 Zustände geben. Normaleweise denkt man so while ((UCSR1A & BitMaske) <> 0) oder while ((UCSR1A & BitMaske) == 0) Nun gilt aber im C 1.) != statt <> 2.) kann man diese Schreibweise abkürzen durch Weglassen des Vergleiches, und das ist sau doofe C Syntax Also es wird dann so while (UCSR1A & BitMaske) do solange in UCSR1A and Bitmaske <> 0 ist mache das while (!(UCSR1A & BitMaske)) do solange NICHT in USCR1A and Bitmaske <> 0 ist mache das, also solange in USCR1A ad Bitmaske == 0 ist mache das Das ist eben C Syntax, und in moderneren Sprache kommt man wieder zurück zu der expliziten Schreibweise. Also das was man denkt und liest schreibt man auch explizit hin. Bitte Leute, keine Diskussionen ob diese Syntax schlecht oder gut ist. Ich weiß nur das meine Lehrlinge exakt damit immer Probleme hatten. Gruß Hagen Hagen Re wrote: > Bitte Leute, keine Diskussionen ob diese Syntax schlecht oder gut ist. > Ich weiß nur das meine Lehrlinge exakt damit immer Probleme hatten. Nee, nicht "gut" oder "schlecht", das ist tatsächlich Geschmackssache. Aber Spock würde korrekterweise anmerken: "Faszinierend, die Syntax ist logisch..." Man muss einfach daran denken, dass in solchen Anweisungen Wahrheitswerte ausgewertet werden, und ein Wahrheitswert kann nunmal nur zwei Zustände annehmen, nämlich wahr oder falsch. Und man sollte wenigstens versuchen, seinen Lehrlingen/Studenten/Wasauchimmer das Denken in logischen Operationen nahezubringen. Klar, es gibt immer Leute, die sich damit schwerer tun als andere, aber: Es ist logisch...;-)
Gast
#652850
Ok dann hier nochmal ob ich es verstanden habe.... UCSR1A ist im Moment wenn ich in die while schleife eintrete so 00100000 wobei die 1 gerade UDRE1 ist. So nun kommt meine Anweisung while (!(UCSR1A & (1<<UDRE1))) Die Schleife dürfte jetzt nicht durchlaufen werden, da 00100000 & 00100000 wieder 00100000 ergeben und das doch wahr ist??? Bin ich doof, ich blick das nicht HILFE....... ;-( Lehrling.de @Johannes, das bestreite ich nicht. Aber es soll Menschen geben die Logik anderst sprechen und denken als das was die C Entwickler darunter cerstanden als sie die C Syntax erschafften ;) Da ich ebenfalls Logik anderst beigebracht bekommen habe, so wie man es eben spricht, muß ich ebenfalls bei komplexeren C Abfrage immer noch im Kopf umformulieren. Gruß Hagen Bastler wrote: > Ok dann hier nochmal ob ich es verstanden habe.... > > UCSR1A ist im Moment wenn ich in die while schleife eintrete so > 00100000 wobei die 1 gerade UDRE1 ist. > > So nun kommt meine Anweisung > > while (!(UCSR1A & (1<<UDRE1))) > > Die Schleife dürfte jetzt nicht durchlaufen werden, da > > 00100000 > & > 00100000 > > wieder > > 00100000 > ergeben und das doch wahr ist??? > Bin ich doof, ich blick das nicht HILFE....... ;-( > Lehrling.de Wenn UDRE1 im Header als "5" definiert ist, dann hast Du das richtig verstanden. Dann steht da im Klartext
und "1 << 5" ist 00100000. Das mit dem UCSR1A bitweise verUNDet gibt 00100000 zurück (wobei es sogar egal ist, welchen Zustand die anderen Bits im UCSR1A haben, denn 00100000 & XX1XXXXX gibt das selbe zurück). 00100000 wird jetzt mit dem logischen (!) Negierungsoperator "!" verarbeitet. Dieser gibt genau dann eine 1 zurück, wenn der Operand 0 ist. Der ist aber nicht 0, sondern 00100000, was ungleich Null und deshalb wahr ist. "!" gibt also eine 0 zurück. Dann steht da "while(0)". Demnach wird nicht in die Schleife hineingesprungen. @Bastler: nochmal, in jeder Abfrage von IF und WHILE muß es zu einer Boolschen Formel kommen. Also immer nur JA oder NEIN. Jede der kompakten, vereinfacht geschriebenen Abfragen in C kann man auch anders schreiben, nämlich so while (X != 0) <- ungleich, <> oder eben while (X == 0) Das lässt sich dann kürzer schreiben while (X) oder while (!(X)) <- solange NICHT (X ungleich 0) Viele Profi-C'ler verkürzen es auf diese Weise, einerseits weil man es in der Mathematik der Boolschen Abfragen auch so schreibt, und andererseit weil man so zeigen kann das man Profi "ist". 0 ist also immer bool'sch FALSCH, und alles was nicht 0 ist ist bool'sch gesehen WAHR. Gruß Hagen 2 Dinge: * In C hat praktisch jeder Ausdruck einen Ergebnis-Wert. Auch eine Zuweisung hat einen Wert, nämlich den Wert der zugewiesen wurde. Das macht Dinge wie i = j = 5; möglich. Auch ein Vergleich ist nichts anderes als ein Ausdruck, der einen Wert liefert: i == 5 liefert 0 (FALSCH) oder 1 (WAHR) je nachdem, ob i eben 5 ist oder nicht. Dies macht Dinge wie j = ( i == 5 ); möglich, wo das Ergebnis eines Vergleiches in einer Variablen abgespeichert wird. Ein Vergleich ist auch nichts anderes als ein 'arithmetischer Ausdruck' (im Englischen: eine Expression) so wie 2 + 3 auch. Während 2 + 3 als Ergebnis 5 liefert, so liefert halt der Ausdruck 5 == 7 eine 0 als Ergebnis. * Wahrheitswerte sind nichts anderes als ganze Zahlen, wobei 0 die Bedeutung von FALSCH (FALSE) besitzt und alles was nicht 0 ist, die Bedeutung WAHR (TRUE) besitzt. In C gibt es keine expliziten boolschen Datentypen, man nimmt einfach obige Konvention her und benutzt einen Ganzzahltyp. Bolsche Werte sind also auch nur Zahlen und auch umgekehrt: jede Zahl kann auch als boolscher Wert fungieren, wobei das allerdings beim while gar nicht zum tragen kommt. In C prüft eine while Schleife eiegentlich gar nicht, ob der angegebene Ausdruck nun TRUE oder FALSE ergibt, sondern es wird (in Ermangelung eines expliziten Boolschen Typen) geprüft, ob der Ausdruck 0 oder eben nicht 0 (in Übereinstimmung mit der Konvention für boolsche Auswertung, siehe Punkt 2 da oben) ist. Das ist alles, was man wissen muss um zu verstehen, warum while (!(UCSR1A & (1<<UDRE1))) so ausgewertet wird, wie es wird. Entweder der Ausdruck !(UCSR1A & (1<<UDRE1)) ergibt 0 oder ergibt nicht 0. Hagen Re wrote: > @Johannes, das bestreite ich nicht. Aber es soll Menschen geben die > Logik anderst sprechen und denken als das was die C Entwickler darunter > cerstanden als sie die C Syntax erschafften ;) > > Da ich ebenfalls Logik anderst beigebracht bekommen habe, so wie man es > eben spricht, muß ich ebenfalls bei komplexeren C Abfrage immer noch im > Kopf umformulieren. Ich glaube nicht, daß das nur ein C-Problem ist. Wer MCs programmieren will, muß einfach wissen, wie Binärzahlen aufgebaut sind und wie bitweise Operatoren (~,&,|,^) funktionieren. Das sind Grundlagen, da kommt keiner drumrum. Es ist schon richtig, daß C auch logische Operatoren (!,&&,||) kennt, damit kann man komplexe if,else-Ketten besser lesbar darstellen. Aber warum zum Teufel gibts kein ^^ ? Peter Peter Dannegger wrote:
> Aber warum zum Teufel gibts kein ^^ ?
Das gibt's, das heißt aber !=.
wäre dasselbe wie
Wenn's dir besser gefällt, kannst du also #define ^^ != schreiben. ;-) (Obiges trifft natürlich nur zu, wenn auf beiden Seiten echte Wahrheitswerte stehen, also nur 0 und 1 zugelassen sind.) Jörg Wunsch wrote: > Peter Dannegger wrote: > >> Aber warum zum Teufel gibts kein ^^ ? > > Das gibt's, das heißt aber !=. Ich denke, Peter meinte mit ^^ das Potenzieren.
Gast
#652908
Ok vielen Dank an euch alle, ich denke jetzt hab ich es auch kappiert. Bitte streitet euch jetzt nicht ob C gut oder schlecht ist. Könnte ich schon so gut programmieren wie ihr, würde ich es für gut ansehen :-) Danke nochmal Gruß Azubi Jörg Wunsch wrote: > Wenn's dir besser gefällt, kannst du also > > #define ^^ != > > schreiben. ;-) (Obiges trifft natürlich nur zu, wenn auf beiden > Seiten echte Wahrheitswerte stehen, also nur 0 und 1 zugelassen > sind.) Leider. Man kann dann nicht schreiben:
Peter Peter Dannegger wrote: > Man kann dann nicht schreiben: > >
Bastler wrote:
> Bitte streitet euch jetzt nicht ob C gut oder schlecht ist.
Hier geht es nicht um gut oder schlecht.
In einigen Bereichen von C hat man sich überlegt, ob man die
überhaupt braucht. So zb. bei boolschen Dingen
Und man ist zu den Schluss gekommen: Nein, eigentlich brauchen
wir die ja gar nicht. Mann muss nur seine Sichtweise der Dinge
etwas verändern.
Während in vielen anderen Sprachen die Syntax (vereinfacht)
so aussieht
if Ausdruck Vergleichsoperator Ausdruck then
hat man sich überlegt: Was wäre, wenn so ein Vergleichsoperator
auf einer Stufe mit den anderen arithmetischen Operatoren wie
+ - * / stehen würde, also einfach auch nur seine beiden
Operanden miteinander verknüpft und ein arithmetisches Ergebnis
liefern würde.
Und man ist zu dem Schluss gekommen, das das durchaus geht, dass
man also die Syntax von if, while vereinfachen kann zu
if Ausdruck then
Natürlich braucht man noch eine Konvention dafür, wie denn das
Ergebnis des Ausdruckes sein muss, damit der then Zweig genommen
wird, aber das ist eine Frage von Konventionen und man entschied
sich für die 0 - nicht 0 Regel.
Aber: Durch den Wegfall eines expliziten bool Typen konnte man
die Sprache einfacher halten ohne das es zu Einbussen gekommen
wäre, ganz im Gegenteil, man erhielt neue Freiheiten.
So kann man in C schreiben:
i = ( j == 5 ) * a + 3 * ( k < 8 );
Ein Vergleichsoperator liefert ja 1 wenn der Vergleich zutrifft
und 0 wenn er nicht zutrifft. Dementsprechen ist das Ergebnis
von ( j == 5 ) * a, genau dann a wenn j gleich 5 ist (weil ja
1 * a wieder a ergibt, während 0 * a immer 0 ist).
In Langform ist obiges also
if( j == 5 )
i = a;
else
i = 0;
if( k < 8 )
i = i + 3;
ok. zugegeben. Die kompremierte Syntax ist für den Anfang etwas
schwer zu lesen. Wenn man sich aber mal dran gewöhnt hat, dann
kommt sie einem relativ natürlich vor. Und klarerweise benutzt
man sowas eher selten (da es meist relativ sinnlos ist). Aber
man kann zb das hier machen:
foo( a, b, i == 5 );
anstelle von
if( i == 5)
foo( a, b, 1 );
else
foo( a, b, 0 );
und das sieht man schon etwas häufiger.
Das führte aber zwangsläufig dazu das sich die Syntaxgrenzen zwischen den einzelnen Sprachelementen verwischten. Also Zuweisung und Boolsche Abfragen in einem einzigsten Konstrukt. Und das wäre mein Hauptkritikpunkt an C. Andere Sprache reduzierten absichtlich diese Möglichkeiten der sehr flexiblen Schreibweisen für den gleichen Sachverhalt, die restriktiven Sprachen. Solche erlernt man viel leichter und intuitiver als C. Wichtig ist aber letzendlich nur eines: Hat man sich in C rein-"gequält" wird es immer mehr Spaß machen. Ein Vorteil ist eben auch das wenn man C kann wird man die einfacheren restriktiven Sprachen leichter erlernen. Ich kann eben bestätigen das gerade bei diesen Syntaxkonstrukten die Lehrlinge die meisten Probleme haben und Fehler machen. Bevor das nicht sitzt braucht man die Pointerarithmetiken garnicht anfangen. Gruß Hagen Nun ist C auch nicht dazu gedacht, als Lehr- oder Unterrichtssprache genutzt zu werden, sondern primär als Werkzeug. Und das hat halt auch Eigenschaften, die es dem, der es kennt, sehr einfach machen, sie zu nutzen, die aber dem, der es nicht kennt, nur sehr schwer zu vermitteln sind. C ist nicht Pädagogik. Programmieren ist auch nicht Pädagogik. Pädagogik im Sinne einiger mehr oder weniger brauchbarer Lehr- und Unterrichtssprachen kommt aus dem Hause Wirth*. *) Niklaus Wirth, Pascal, Modula(2), Oberon ... Eines sollte aber das Andere nicht ausschließen. Wenn es einen Job gibt bei dem man nie auslernt dann wohl Programmierung, oder ? Gruß Hagen Hagen Re wrote: > Wichtig ist aber letzendlich nur eines: Hat man sich in C rein-"gequält" > wird es immer mehr Spaß machen. Das sicherlich. Wenn ich jemanden in die Grundzüge von C einführe, fang ich auch nicht mit diesen Kurzschreibweisen an, sondern achte darauf, dass er die Langformen benutzt if( i == 0 ) if( ptr == NULL ) Irgendwann studiert er dann auch mal andere Programme und dann kann man ihn langsam an die "Wahrheit" heranführen und schrittweise in die Geheimnisse der Kurzschreibweisen einführen. Die ersten davon werden sicherlich ++, --, +=, -= usw. sein. > > Ich kann eben bestätigen das gerade bei diesen Syntaxkonstrukten die > Lehrlinge die meisten Probleme haben und Fehler machen. Das glaub ich gerne. > Bevor das nicht > sitzt braucht man die Pointerarithmetiken garnicht anfangen. :-) Die nächste große Hürde. Danach kommt noch der Übergang von 1-Stern Programmierung zu 2-Stern Programmierung, der erstaunlicherweise (obwohl völlig logisch) auch immer wieder zu Problemen führt Karl heinz Buchegger wrote: > Danach kommt noch der Übergang von 1-Stern Programmierung zu > 2-Stern Programmierung, der erstaunlicherweise (obwohl völlig > logisch) auch immer wieder zu Problemen führt Wenn sie dann endlich denken, sie hätten C schon verstanden, kann man sie noch mit dem ternären operator (?:) überraschen. Anschließend kommt als Prüfungsaufgabe das Schreiben einer Funktion, die einen Zeiger auf den Typ ihrer selbst übernimmt und einen ebensolchen zurück gibt, und zwar ohne Benutzung von typedef. :-)) Schließlich und endlich blieben noch geschachtelte obskure Präprozessorkonstrukte übrig, in denen es von # und ## nur so wimmelt. ;-) Antwort schreibenBitte melde dich an, um einen Beitrag zu schreiben. |
Anzeige
|