Unklarheiten bei einem C Programm

Gast #4827187
Lesenswert?

>Warum schreibt man denn
>PORTC = (0<<DDC0);
>anstelle
>PORTC = 0;

Bwiwrkt beides dasselbe, ich weiss auch nicht was das soll.

Falls der Programmierer lediglich das Bit vom dem if Statement wieder 
auf 0 setzen wollte, hat er es falsch gemacht, er setzt alle Bits auf 
null.

Womöglich wollte der Programmierer folgendes:
1
if(ACSR & (1<<ACO))
2
{
3
  PORTC |= (1<<DDC0);
4
}
5
else
6
{
7
  PORTC &= ~(1<<DDC0);
8
}
Gast #4827195
Lesenswert?

Dr. Ötte schrieb:
> Warum schreibt man denn
>
> PORTC = (0<<DDC0);
>
> anstelle
>
> PORTC = 0;
Wer tut das? Es bewirkt das Gleiche, wenn der Compiler zumindest ein 
bisschen optimiert, aber das untere ist verständlicher.

xXxPu55YD35TrOyEr69xXx schrieb:
> Und was soll das Linksschieben bewirken? Wäre mehr als dankbar für ne
> kurze Erklärung.
Man nimmt eine 1 (0001) und schiebt die um eine gewisse Anzahl an 
Stellen nach links. Bei zwei Stellen wäre das dann 0100. Damit setzt man 
das Bit Nummer zwei.
Gast #4827200
Lesenswert?

>> Das schreibt man nur dann so, wenn man nicht verstanden hat, daß es
>> völlig sinnlos ist, Nullen durch die Gegend zu schieben.
>Ohne Optimierung ergibt das ein paar verschleierte NOP ;-)

Nope, das gibt nicht mal ohne optimierung NOPs, Konstanten löst bereits 
der C-Präprozessor auf.
Gast #4827202
Lesenswert?

if(ACSR & (1<<ACO)

Schlumpf Dir mal das Datenblatt des verwendeten Mikrokontrollers. Da 
gibt es bestimmt ein Special Function Register (SFR) mit dem schönen 
Namen ACSR.
Eines der darin enthaltenen Bits nennt sich ACO.
Was dieses Bit aussagt, findest Du im Datenblatt.

Weiterhin hat Dir ein netter Mensch schon mal was vorbereitet, damit Du 
schön bequem auf dieses Bit zugreifen kannst.
Er hat Dir das SFR unter dessen Namen ACSR zugänglich gemacht. Und er 
hat ein Define mit der Bitnummer für ACO angelegt. Ist doch toll.

Wenn man also jetzt eine 1 so oft nach links schiebt wie die Bitnummer, 
dann hat man danach eine Zahl in der genau nur das Bit mit dieser Nummer 
gesetzt ist.
Wenn man so eine Zahl, die man auch Maske nennt, mit einem Wert und 
verknüpft, überlebt nur das eine Bit, alle anderen sind danach 0.

Die if-Anweisung hält die Bedingung für wahr, wenn ein Wert ungleich 0 
heeraus kommt. Wenn der Wert der Bedingung gleich 0 ist, wird die 
Anweisung/der Block, der dem if zugeordnet ist nicht ausgeführt.

kurz gesagt, wenn Bit ACO in ACSR gesetzt...

PORTC = (0<<DDC0);
nicht zu erklären, da blöder Fehler
PORTC &= ~(1<<DDC0);
währe Ihr Preis gewesen.
Gast #4827212
Lesenswert?

Und wenn ich (1<< PB0) schreibe, dann setze ich PB0 doch auf high?

Wenn du den Pin vorher in den Outputmodus geschaltet hast, ja.


BP0 ist als 0 definiert, damit ergibt (1<<BP0)==1=='0b00000001'
Gast #4827217
Lesenswert?

Peter II schrieb:
> Mikel schrieb:
>> Nope, das gibt nicht mal ohne optimierung NOPs, Konstanten löst bereits
>> der C-Präprozessor auf.
>
> sicher? Ich dachte er rechnet nur bei #ifdef sonst NIE.

Wenn du zum Beispiel schreibst: c = 3 + 5;
Dann setzt er eine 8 ein. Der Compiler bekommt die 3 und die 5 niemals 
zu sehen.
Gast #4827238
Lesenswert?

Peter II schrieb:
> Huh schrieb:
>> Wenn du zum Beispiel schreibst: c = 3 + 5;
>> Dann setzt er eine 8 ein. Der Compiler bekommt die 3 und die 5 niemals
>> zu sehen.
>
> das schein mein GCC andere Meinung zu sein.
Das wage ich auch mal zu bezweifeln. Dafür müsste doch der Präprozessor 
den Code selber parsen und damit viel mehr 'Intelligenz' haben, als er 
eigentlich braucht.
Es kann sein, dass heutige Präprozessoren das können, aber ist das 
grundsätzlich oder zumindest normalerweise so?
Gast #4827241
Lesenswert?

Dussel schrieb:
> Das wage ich auch mal zu bezweifeln.

es ist auch nicht so.
1
#include <stdio.h>
2

3
#define V1 12
4
#define V2 8
5

6
int main() {
7
  int a = V1 + V2;
8
  printf("%d", a );
9
}
10
[c]
11

12
erzeugt nach dem Prä
13
[c]
14
# 6 "test.c"
15
int main() {
16
  int a = 12 + 8;
17
  printf("%d", a );
18
}
Gast #4827389
Lesenswert?

xXxPu55YD35TrOyEr69xXx schrieb:
> Ich suche Erklärungen für diese Befehle.
1
  /* Ist das ACO (Analog Comparator Output) Bit in ACSR (Analog 
2
    Comparator Control und Status Register) gesetzt?  Heißt soviel wie: 
3
    Hat der Comparator gefeuert? 
4
  */
5
   if(ACSR & (1<<ACO)){ 
6
  
7

8
   
9
    /* Ist vermutlich geballter Schwachsinn. Da wird in PORTC das DDC0 
10
      (Data Direction Control Bit 0) gesetzt.
11
       Nur gehört das DDC0 Bit zum Register DDRC (Data Direction Control 
12
       Register für PORTC), aber nicht zum PORTC.
13
       Wenn der Autor hier schalten wollte, dass Bit 0 von PORTC 
14
       als Ausgang konfiguriert werden sollte, hätte er DDCR statt 
15
       PORTC schreiben sollen. Wollte er einfach Bit0 auf high setzen, 
16
       hätte er besser PC0 statt DDC0 geschrieben. 
17
    */
18
     PORTC |= (1<<DDC0); 
19
   }
20
   else{
21

22

23

24
   /* Wie schon Vorredner geschrieben: gewiss wollte der Autor 
25
      bloß ein einzelnes Bit löschen, löscht statt dessen aber alle. 
26
      Ansonsten der selbe irreführende Register- / Bitnamenmix wie oben. 
27
     */
28
     PORTC = (0<<DDC0);
29
   }


Grundsätzlich ist es eine gute Idee lieber mit Namen (Konstanten) statt 
mit Zahlen zu arbeiten. Das macht Code leserlicher und verdeutlicht die 
Intension. Deswegen schreibt man lieber auch mal (0<<DDC0)  statt 
einfach nur 0. Denn die 0 alleine kann nicht ausdrücken, dass man 
explizit das Data Direction Control Bit gemeint hatte. Ist ein bißchen 
wie der Unterschied zwischen "Ey du da, dritter Sohn von neun!" und "Ey, 
Klaus!".
Gast #4827502
Lesenswert?

Nur zur Klarstellung:

Dem TO ging es wohl nur um die völlig dämliche Zeile

> PORTC = (0<<DDC0);

Die anderen Dinge (Bit abfragen, Bit testen) sind ihm klar.

Die Zeile mit 0<< ist ein bedauerlicher Schreibfehler oder wurde von 
einem Bastler durch "probieren" herausgefunden.

Mikel, TO und vermutlich andere haben gepostet, wie man es richtig 
macht.
Gast #4827533
Lesenswert?

Rufus Τ. F. schrieb:
> Kurt schrieb:
>> Da wird in PORTC das DDC0 (Data Direction Control Bit 0) gesetzt.
>
> Es wird nicht gesetzt, es wird abgefragt.

Das bezog sich auf die Zeile
1
PORTC |= (1<<DDC0);
Diese Zeile fragt nichts ab, sondern schaltet PC0 auf high. Zumindest 
wenn das DDRC dafür als Ausgang gesetzt ist. Nach Präprozessor und 
Optimierung im Compiler wird daraus wohl:
[a]sbi PORTC, 0;[/a]

Rainer B. schrieb:
> Kurt schrieb:
>> Deswegen schreibt man lieber auch mal (0<<DDC0)  statt
>> einfach nur 0
> Dann verrate uns bitte mal, wie du mit dieser sinnfreien 0-Schieberei
> einzelne Bits eines Registers löschen willst.
> Alles zum Thema 0-Schieberei hat Rufus oben bereits gesagt.

Da wird ja nicht wirklich was geschoben. Dass es sinnfrei ist Nullen zu 
shiften weiß auch der Compiler und optimiert das weg. Aber der Schreiber 
/ Leser des Codes kann so ausdrücken um welches Bit es ihm geht. Und 
genau diese hier so oft gescholtene, müffelige Zeile zeigt den Grund, 
warum das vorteilhaft ist:
1
PORTC = (0<<DDC0);

So kann man schon beim Lesen des Codes erkennen, dass der Autor hier mit 
99% Sicherheit einen Fehler gemacht hat: alle 8 Bits statt nur Bit0 zu 
löschen. Hätte er nur
1
PORTC = 0;
 geschrieben, wäre man davon ausgegangen, dass das Absicht und kein 
Fehler war. Die Pseudo-Bitshifterei dient einzig dem Zweck die Intension 
im Code zu formulieren.
Gast #4827651
Lesenswert?

Oft wird (0<<XYZ) aus optischen Gründen verwendet (ja, ein Quellcode 
sollte auch schön und lesbar sein).

Beispiel

A = (1<<AX5) | (0<<AX4) | (1<<AX3) | (1<<AX2) | (0<<AX1);

Natürlich sind die ganzen (0<<AX) vom Code her sinnlos.
Das hat aber eine andere Aussage als

A = 0b10110;

Ein Quellcode ist nicht für den Computer, sondern für den Menschen 
gedacht.
Ich lese einen optisch schönen und sauberen Code lieber, als zusammen 
gequetschten Wirrwar ohne Kommentare. Ist der Code aber gut genug, 
braucht man keine Kommentare.

Man muss also nicht alles verteufeln, was für den Computer sinnlos ist.
Gast #4829554
Lesenswert?

So lasse ich mir das gefallen, da sieht man, welche Bits gesetzt sind, 
und kann es schnell ändern. Ok, wenn es ein Byte ist, werden 3 weitere 
Bits kommentarlos auf 0 gesetzt.
1
A = (1<<AX5) | (0<<AX4) | (1<<AX3) | (1<<AX2) | (0<<AX1);

Aber bei dem folgenden Ausdruck macht man dem eiligen Leser weiss, hier 
würde nur Bit DDC0 geändert. In Wirklichkeit wird aber das komplette SFR 
PORTC auf 0 gesetzt. Ein Quell der Freude, wenn man mal DDC1 benutzt und 
puff ist es 0 und niemand weiss warum. Da finde ich es klarer = 0 zu 
schreiben.
1
PORTC = (0<<DDC0);
Gast #4829616
Lesenswert?

Hihi, es ist ja noch schlimmer. In der 'Bitmaske' wird DDC0 (ein Bit aus 
DDRC) genannt, aber gelöscht wird PORTC - also die Bits PC0..PC7.

fop schrieb:
> Ein Quell der Freude, wenn man mal DDC1 benutzt und
> puff ist es 0 und niemand weiss warum.

DDC1 wird von dem Code nicht berührt. Aber wenn Du eigentlich PC1 
meinst, dann hast Du voll Recht! Auf jeden Fall ist in der Zeile ein 
Schaf das knurrt und bellt, egal wie unschuldig es auszusehen versucht.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren