if (uint16_t) --blink) == 0 Ok. if(--blink == 0 ) nicht ok?

OP #3863230
Lesenswert?

Hallo,

ich stehe auf dem Schlauch. Wieso erkennt der Compiler im oberen Teil 
nicht einen 16 bit wert? Beides compiliert ohne Hinweis bzw. Fehler.
1
#include <avr/io.h>
2
#include <inttypes.h>
3

4
uint16_t blink=24;
5

6
int main()
7
{
8
#if 0
9
  if(--blink == 0 ){
10
    PORTB = PINB ^ ( 1 << PB0 );
11
    blink=24;
12
  }
13
#else
14
  if( ((uint16_t) --blink) == 0 ){
15
    PORTB = PINB ^ ( 1 << PB0 );
16
    blink=24;
17
  }
18
#endif
19
}
Gast #3863506
Lesenswert?

Kaj schrieb im Beitrag #3863492
>
> Das ist so ziemlich die beschissenste art etwas "auszukommentieren"!

Ok. Ich schlage vor:
Du schreibst jetzt, wie du Code kurzfristig "rausnehmen" würdest und ich 
sag dir nachher wieso die Methode vomTO besser ist.
Gast #3863520
Lesenswert?

Kaj schrieb:
> Jörg Esser schrieb:
>> #if 0
>> #else
>> #endif
>
> Das ist so ziemlich die beschissenste art etwas "auszukommentieren"!

Alternativvorschlag? Mir fallen spontan mehrere Gründe ein, weshalb das 
hier durchaus in Ordnung ist...
Aber lass du mal hören!
(Firma: keine) #3863617
Lesenswert?

Vermutung ins Blaue: Compileroptimierung

Für die Variable gilt immer 0 <= blink <= 24. Kann also sein, dass der 
Compiler das in der ersten Version platzsparend in ein uint8_t 
umwandelt. Bei der zweiten Variante hingegen castest du explizit wieder 
zu uint16_t -> keine Optimierung da uint16_t explizit gefordert.
#3863623
Lesenswert?

Thomas Eckmann schrieb:
> Editoren gibt es nicht. Editor ist Singularetantum, da es nur einen
> Editor gibt.

Der Duden lässt das Plural zu, das ist deine Aussage rein 
grammatikalisch wohl nicht ganz zutreffend. Bei der hier etwas 
deplacierten Bedeutung im Verlagswesen klappt das auch nicht, denn 
selbstredend gibt es mehrere Editoren/Herausgeber, andernfalls wäre die 
Medienlandschaft noch trister als sie ohnehin schon ist.
#3863631
Lesenswert?

A. K. schrieb:
> Der Duden lässt das Plural zu, das ist deine Aussage rein
> grammatikalisch wohl nicht ganz zutreffend. Bei der hier etwas
> deplacierten Bedeutung im Verlagswesen klappt das auch nicht, denn
> selbstredend gibt es mehrere Editoren/Herausgeber, andernfalls wäre die
> Medienlandschaft noch trister als sie ohnehin schon ist.

Nein. Es gibt nur einen Editor. Alles andere ist Spielkram.

mfg.
#3863649
Lesenswert?

Thomas Eckmann schrieb:
> A. K. schrieb:
>> Der Duden lässt das Plural zu, das ist deine Aussage rein
>> grammatikalisch wohl nicht ganz zutreffend. Bei der hier etwas
>> deplacierten Bedeutung im Verlagswesen klappt das auch nicht, denn
>> selbstredend gibt es mehrere Editoren/Herausgeber, andernfalls wäre die
>> Medienlandschaft noch trister als sie ohnehin schon ist.
>
> Nein. Es gibt nur einen Editor. Alles andere ist Spielkram.
>
> mfg.


Autor: Thomas Eckmann (Firma: Thomas Eckmann Informationst.) (thomase)
Hmm, was sind den "thomase" ? Doch nicht etwa die Mehrzahl von dir. ;)
#3863662
Lesenswert?

Detlef Kunz schrieb:
> Autor: Thomas Eckmann (Firma: Thomas Eckmann Informationst.) (thomase)
> Hmm, was sind den "thomase" ? Doch nicht etwa die Mehrzahl von dir. ;)

Doch. Normalerweise hast du mich mit Ihr bzw. Euch anzureden.

Jetzt mach hier nicht so einen Wind. Du verstehst das nur nicht.

Das bezog sich einzig auf unseren Linuxfreund, der hier mit seinem vim 
angeben wollte.

Richtige Linuxuser, also die Masochisten unter den Linuxusern, naja 
eigentlich sind das ja alles Masochisten, aber egal.

Also für die richtigen, die knallharten Linuxuser gibt es nur einen 
Editor. Ich hatte ja befürchtet, dass das keiner versteht und extra 
einen Zaunpfahl zum winken eingebaut: Wie? Ei,...

mfg.
#3863674
Lesenswert?

Jörg Esser schrieb:
> Hmm bei mir gibt es einen Unterschied. Die Variable wird scheinbar
> anders heruntergezählt.
Da musst du dich irren.

Es gibt 2 Regeln:

1. Der Compiler hat immer Recht.
2. Trifft dies ausnahmsweise nicht zu, tritt automatisch Regel 1 in 
Kraft.

Mit anderen Worten: Was der Compiler macht, ist richtig.
Und er gehorcht dir aufs Wort. Und zwar richtig wörtlich. Manchmal gibt 
es allerdings Verständigungsprobleme. Dann kommen die beiden Regeln zum 
Zuge.

Aber das ist hier nicht der Fall. Der zählt runter oder besser er lässt 
runterzählen. Da kann er gar nicht anders.

mfg.
Gast #3863682
Lesenswert?

>Thomas Eckmann (Firma: Thomas Eckmann Informationst.) (thomase)

Bist du einer dieser fahrenden Computerbeschwörer deren Kenntnisse man 
sich dann und wann an nicht funktionierenden SOHO Installationen 
überzeugen darf? Zumindest ereilt mich an dieser Stelle so ein 
Eindruck...

MfG
Gast #3863692
Lesenswert?

Jörg Esser schrieb:
> Hmm bei mir gibt es einen Unterschied. Die Variable wird scheinbar
> anders heruntergezählt.
> Ich werde mal schaun was mein gcc für einen assembler code ausspuckt.
>
> Sorry für meine Laienhaften Ausführungen aber das is für mich nur Hobby
> bzw. Liebhaberei ;)

Pack doch einfach mal das .lss File hier rein, dann können wir sehen wie 
unterschiedlich das Ergebnis ausfällt.
#3864123
Lesenswert?

Jörg Esser schrieb:
> Hallo,
>
> ich stehe auf dem Schlauch. Wieso erkennt der Compiler im oberen Teil
> nicht einen 16 bit wert? Beides compiliert ohne Hinweis bzw. Fehler.
>
1
> #include <avr/io.h>
2
> #include <inttypes.h>
3
> 
4
> uint16_t blink=24;
5
> 
6
> int main()
7
> {
8
> #if 0
9
>   if(--blink == 0 ){
10
>     PORTB = PINB ^ ( 1 << PB0 );
11
>     blink=24;
12
>   }
13
> #else
14
>   if( ((uint16_t) --blink) == 0 ){
15
>     PORTB = PINB ^ ( 1 << PB0 );
16
>     blink=24;
17
>   }
18
> #endif
19
> }
20
>

Ich könnte mir vorstellen, dass der Compiler optimiert.
Da nur 0..24 als Wert vorkommt, reicht es, diesen Wert als 8Bit zu 
speichern (AVR 8Bit Controller), dafür ist nur ein 8Bit-Register 
notwendig - im oberen Fall.
Unten castest du explizit zu uint16_t, der Compiler gehorcht aufs Wort 
und belegt 16Bit.
#3864155
Lesenswert?

Daniel V. schrieb:
> Ich könnte mir vorstellen, dass der Compiler optimiert.
> Da nur 0..24 als Wert vorkommt, reicht es, diesen Wert als 8Bit zu
> speichern (AVR 8Bit Controller), dafür ist nur ein 8Bit-Register
> notwendig - im oberen Fall.
> Unten castest du explizit zu uint16_t, der Compiler gehorcht aufs Wort
> und belegt 16Bit.

Klingt sinnvoll. Bei komplett abgeschalteter Optimierung sollte dann das 
gleiche Ergebnis herauskommen.
Persönliche Seite #3864241
Lesenswert?

Daniel V. schrieb:
> Ich könnte mir vorstellen, dass der Compiler optimiert.
> Da nur 0..24 als Wert vorkommt, [...]

Diese Annahme ist falsch, bzw. ein Compiler, der so eine Annahme oder 
darauf basierende Optimierungen macht, ist nicht korrekt.

Beim Aufruf von main ist der Wert der Variablen nämlich nicht bekannt: 
Ein anderes Modul könnte Code vor main ausführen und blink auf einen 
anderen Wert setzen.
Moderator #3864245
Lesenswert?

Ich glaube kaum, dass Jörg mit dem GCC einen Unterschied zwischen den
beiden Varianten feststellen konnte. Ich hab's gerade für verschiedene
Compiler-Versionen, Optimierungsstufen und AVR-Typen ausprobiert. Der
vom Compiler erzeugte Assemblercode hängt in allen Fällen nicht davon
ab, welcher Zweig im #if-#else-#endif aktiv ist.

Ergebnis:
1
avr-gcc-4.2.4 -O0 -mmcu=attiny13        --> gleich
2
avr-gcc-4.2.4 -O0 -mmcu=atmega1280      --> gleich
3
avr-gcc-4.2.4 -O1 -mmcu=attiny13        --> gleich
4
avr-gcc-4.2.4 -O1 -mmcu=atmega1280      --> gleich
5
avr-gcc-4.2.4 -O2 -mmcu=attiny13        --> gleich
6
avr-gcc-4.2.4 -O2 -mmcu=atmega1280      --> gleich
7
avr-gcc-4.2.4 -O3 -mmcu=attiny13        --> gleich
8
avr-gcc-4.2.4 -O3 -mmcu=atmega1280      --> gleich
9
avr-gcc-4.2.4 -Os -mmcu=attiny13        --> gleich
10
avr-gcc-4.2.4 -Os -mmcu=atmega1280      --> gleich
11

12
avr-gcc-4.3.6 -O0 -mmcu=attiny13        --> gleich
13
avr-gcc-4.3.6 -O0 -mmcu=atmega1280      --> gleich
14
avr-gcc-4.3.6 -O1 -mmcu=attiny13        --> gleich
15
avr-gcc-4.3.6 -O1 -mmcu=atmega1280      --> gleich
16
avr-gcc-4.3.6 -O2 -mmcu=attiny13        --> gleich
17
avr-gcc-4.3.6 -O2 -mmcu=atmega1280      --> gleich
18
avr-gcc-4.3.6 -O3 -mmcu=attiny13        --> gleich
19
avr-gcc-4.3.6 -O3 -mmcu=atmega1280      --> gleich
20
avr-gcc-4.3.6 -Os -mmcu=attiny13        --> gleich
21
avr-gcc-4.3.6 -Os -mmcu=atmega1280      --> gleich
22

23
avr-gcc-4.4.7 -O0 -mmcu=attiny13        --> gleich
24
avr-gcc-4.4.7 -O0 -mmcu=atmega1280      --> gleich
25
avr-gcc-4.4.7 -O1 -mmcu=attiny13        --> gleich
26
avr-gcc-4.4.7 -O1 -mmcu=atmega1280      --> gleich
27
avr-gcc-4.4.7 -O2 -mmcu=attiny13        --> gleich
28
avr-gcc-4.4.7 -O2 -mmcu=atmega1280      --> gleich
29
avr-gcc-4.4.7 -O3 -mmcu=attiny13        --> gleich
30
avr-gcc-4.4.7 -O3 -mmcu=atmega1280      --> gleich
31
avr-gcc-4.4.7 -Os -mmcu=attiny13        --> gleich
32
avr-gcc-4.4.7 -Os -mmcu=atmega1280      --> gleich
33

34
avr-gcc-4.5.4 -O0 -mmcu=attiny13        --> gleich
35
avr-gcc-4.5.4 -O0 -mmcu=atmega1280      --> gleich
36
avr-gcc-4.5.4 -O1 -mmcu=attiny13        --> gleich
37
avr-gcc-4.5.4 -O1 -mmcu=atmega1280      --> gleich
38
avr-gcc-4.5.4 -O2 -mmcu=attiny13        --> gleich
39
avr-gcc-4.5.4 -O2 -mmcu=atmega1280      --> gleich
40
avr-gcc-4.5.4 -O3 -mmcu=attiny13        --> gleich
41
avr-gcc-4.5.4 -O3 -mmcu=atmega1280      --> gleich
42
avr-gcc-4.5.4 -Os -mmcu=attiny13        --> gleich
43
avr-gcc-4.5.4 -Os -mmcu=atmega1280      --> gleich
44

45
avr-gcc-4.6.4 -O0 -mmcu=attiny13        --> gleich
46
avr-gcc-4.6.4 -O0 -mmcu=atmega1280      --> gleich
47
avr-gcc-4.6.4 -O1 -mmcu=attiny13        --> gleich
48
avr-gcc-4.6.4 -O1 -mmcu=atmega1280      --> gleich
49
avr-gcc-4.6.4 -O2 -mmcu=attiny13        --> gleich
50
avr-gcc-4.6.4 -O2 -mmcu=atmega1280      --> gleich
51
avr-gcc-4.6.4 -O3 -mmcu=attiny13        --> gleich
52
avr-gcc-4.6.4 -O3 -mmcu=atmega1280      --> gleich
53
avr-gcc-4.6.4 -Os -mmcu=attiny13        --> gleich
54
avr-gcc-4.6.4 -Os -mmcu=atmega1280      --> gleich
55

56
avr-gcc-4.7.4 -O0 -mmcu=attiny13        --> gleich
57
avr-gcc-4.7.4 -O0 -mmcu=atmega1280      --> gleich
58
avr-gcc-4.7.4 -O1 -mmcu=attiny13        --> gleich
59
avr-gcc-4.7.4 -O1 -mmcu=atmega1280      --> gleich
60
avr-gcc-4.7.4 -O2 -mmcu=attiny13        --> gleich
61
avr-gcc-4.7.4 -O2 -mmcu=atmega1280      --> gleich
62
avr-gcc-4.7.4 -O3 -mmcu=attiny13        --> gleich
63
avr-gcc-4.7.4 -O3 -mmcu=atmega1280      --> gleich
64
avr-gcc-4.7.4 -Os -mmcu=attiny13        --> gleich
65
avr-gcc-4.7.4 -Os -mmcu=atmega1280      --> gleich
66

67
avr-gcc-4.8.3 -O0 -mmcu=attiny13        --> gleich
68
avr-gcc-4.8.3 -O0 -mmcu=atmega1280      --> gleich
69
avr-gcc-4.8.3 -O1 -mmcu=attiny13        --> gleich
70
avr-gcc-4.8.3 -O1 -mmcu=atmega1280      --> gleich
71
avr-gcc-4.8.3 -O2 -mmcu=attiny13        --> gleich
72
avr-gcc-4.8.3 -O2 -mmcu=atmega1280      --> gleich
73
avr-gcc-4.8.3 -O3 -mmcu=attiny13        --> gleich
74
avr-gcc-4.8.3 -O3 -mmcu=atmega1280      --> gleich
75
avr-gcc-4.8.3 -Os -mmcu=attiny13        --> gleich
76
avr-gcc-4.8.3 -Os -mmcu=atmega1280      --> gleich
77

78
avr-gcc-4.9.1 -O0 -mmcu=attiny13        --> gleich
79
avr-gcc-4.9.1 -O0 -mmcu=atmega1280      --> gleich
80
avr-gcc-4.9.1 -O1 -mmcu=attiny13        --> gleich
81
avr-gcc-4.9.1 -O1 -mmcu=atmega1280      --> gleich
82
avr-gcc-4.9.1 -O2 -mmcu=attiny13        --> gleich
83
avr-gcc-4.9.1 -O2 -mmcu=atmega1280      --> gleich
84
avr-gcc-4.9.1 -O3 -mmcu=attiny13        --> gleich
85
avr-gcc-4.9.1 -O3 -mmcu=atmega1280      --> gleich
86
avr-gcc-4.9.1 -Os -mmcu=attiny13        --> gleich
87
avr-gcc-4.9.1 -Os -mmcu=atmega1280      --> gleich

Durchgenudelt mit diesem Skript:
1
#!/bin/sh
2

3
for gcc in /usr/local/avr/bin/avr-gcc-[0-9]*; do
4
  for opt in 0 1 2 3 s; do
5
    for mcu in attiny13 atmega1280; do
6
      cmd="$(basename $gcc) -O$opt -mmcu=$mcu"
7
      for sel in 0 1; do
8
        $cmd -x c -DSEL=$sel -S -o test$sel.s - <<EOF
9
#include <avr/io.h>
10
#include <inttypes.h>
11

12
uint16_t blink=24;
13

14
int main()
15
{
16
#if SEL
17
  if(--blink == 0 ){
18
    PORTB = PINB ^ ( 1 << PB0 );
19
    blink=24;
20
  }
21
#else
22
  if( ((uint16_t) --blink) == 0 ){
23
    PORTB = PINB ^ ( 1 << PB0 );
24
    blink=24;
25
  }
26
#endif
27
}
28
EOF
29
      done
30
      echo -ne "$cmd\t--> "
31
      if diff test{0,1}.s > /dev/null; then
32
        echo gleich
33
      else
34
        echo verschieden
35
      fi
36
    done
37
  done
38
  echo
39
done

@Jörg:

Folgendes
1
    PORTB = PINB ^ ( 1 << PB0 );

tut nicht immer das, was du damit vermutlich bezweckst, nämlich PORTB0
toggeln und sonst nichts. Wenn nämlich irgendein Pin von Port B als
Eingang genutzt wird, dann wird mit der obigen Anweisung je nach
Eingangspegel der Pullup-Widerstand für diesen Eingang aktiviert bzw.
deaktiviert, was wahrscheinlich nicht beabsichtig ist.

Besser:
1
    PORTB = PORTB ^ ( 1 << PB0 );

Noch besser:
1
    PORTB ^= 1 << PB0;

Falls der von dir eingesetzte AVR ein etwas neuerer ist, der über das
Pin-Toggle-Feature verfügt, noch besser:
1
    PINB |= 1 << PB0;
#3864279
Lesenswert?

Johann L. schrieb:
> Daniel V. schrieb:
>> Ich könnte mir vorstellen, dass der Compiler optimiert.
>> Da nur 0..24 als Wert vorkommt, [...]
>
> Diese Annahme ist falsch, bzw. ein Compiler, der so eine Annahme oder
> darauf basierende Optimierungen macht, ist nicht korrekt.
>
> Beim Aufruf von main ist der Wert der Variablen nämlich nicht bekannt:
> Ein anderes Modul könnte Code vor main ausführen und blink auf einen
> anderen Wert setzen.

Prinzipiell hast du Recht.
Dennoch, so wie es da steht, ohne sonstige Funktionen etc. könnte ich 
sogar noch mehr optimieren und sagen: blink wird NIE 0, also kann ich 
alles weglassen. Es fehlt nämlich die while(1)-Schleife.
Gast #3864378
Lesenswert?

Yalu X. schrieb:
> Falls der von dir eingesetzte AVR ein etwas neuerer ist, der über das
> Pin-Toggle-Feature verfügt, noch besser:
>     PINB |= 1 << PB0;

Bloss nicht, da toggeln u.U. mehr Pins als du willst. Richtig ist
1
PINB = 1<<PB0;
Da bin ich auch schon drauf reingefallen, und man sieht es erst beim 
100. Drueberlesen, da man ja darauf konditioniert ist, bei einer 
Operation auf nur einem Portbit irgendwelche & und | zu sehen.
Moderator #3864422
Lesenswert?

Tassilo schrieb:
> Bloss nicht, da toggeln u.U. mehr Pins als du willst. Richtig ist
>  PINB = 1<<PB0;

Das geht auch, erfordert aber zwei Maschineninstruktionen statt einer.

Dieses
1
    PINB |= 1 << PB0;

sieht zwar auf den ersten Blick falsch aus, ist es aber nicht, da es vom
Compiler in ein SBI umgesetzt wird. Auch das SBI sieht an dieser
Stelle falsch aus (da man dahinter einen Read-Modify-Write-Ablauf
vermutet), ist es aber nicht. In den Datenblättern der entsprechenden
AVRs wird explizit der SBI-Befehl als einen Möglichkeit für die
Toggle-Funktion genannt.
Gast #3864436
Lesenswert?

Gerade nachgesehen, hast recht, falsche Erinnerung. Im Problemfall 
wurden bei mir auch mehrere Bits gleichzeitig getoggelt, dann wird da 
wohl kein SBI mehr draus. Ich sollte nix schreiben ohne nochmals ins 
Datenblatt zu schauen :-/
Gast #3864544
Lesenswert?

Johann L. schrieb:
> Daniel V. schrieb:
>> Ich könnte mir vorstellen, dass der Compiler optimiert.
>> Da nur 0..24 als Wert vorkommt, [...]
>
> Diese Annahme ist falsch, bzw. ein Compiler, der so eine Annahme oder
> darauf basierende Optimierungen macht, ist nicht korrekt.
>
> Beim Aufruf von main ist der Wert der Variablen nämlich nicht bekannt:
> Ein anderes Modul könnte Code vor main ausführen und blink auf einen
> anderen Wert setzen.

In C gibt es offiziell keinen Code vor main().
Gast #3864691
Lesenswert?

So kann man code vor der main() ausführen:
1
void my_init() __attribute__ ((naked))  __attribute__ ((section (".init5")));
2

3
void my_init() {
4
   ...
5
}
6

7
void main() {
8
   ...
9
}

Geht auch, wenn die my_init() funktion in einer anderen Datei liegt, als 
main().
OP #3864707
Lesenswert?

@Yalu
Vielen Dank für den Hinweis. In meinem Fall nutze ich nur den tiny85 und 
der hat nur einen Port wo ich ein paar Pins auf Ein bzw. Ausgang 
geschaltet habe. Ich sollte
meine alten Code mal danach absuchen.

Woran erkenne ich die Unterstützung der neuen Toggle Feature?
Im Datenblatt zu finden?
Ich denke der Tiny ist alt wird wohl nur bei xmega etc geben?

Danke auch an den Rest für die Hilfe.
Moderator #3864813
Lesenswert?

Jörg Esser schrieb:
> Woran erkenne ich die Unterstützung der neuen Toggle Feature?

Ganz so neu ist das auch wieder nicht.

> Im Datenblatt zu finden?

Ja. Bei denen, die toggeln können, findet sich dieser kurze Abschnitt im
Datenblatt:
1
Toggling the Pin
2

3
Writing a logic one to PINxn toggles the value of PORTxn, independent on
4
the value of DDRxn. Note that the SBI instruction can be used to toggle
5
one single bit in a port.


> Ich denke der Tiny ist alt wird wohl nur bei xmega etc geben?

Doch, der ATtiny85 ist relativ neu und hat dieses Feature, der ältere
ATtiny13 aber auch schon. Ich glaube sogar, das gilt für alle ATtiny,
die derzeit hergestellt werden.
Gast #3865283
Lesenswert?

Thomas Eckmann schrieb:
> Das bezog sich einzig auf unseren Linuxfreund, der hier mit seinem vim
> angeben wollte.

Achje.
Ich habe lediglich andeuten wollen, dass es Gang und Gäbe ist Code mit 
#if 0 auszukommentieren. Denn sogar gängige Editoren (Ja Editoren) 
unterstützen das.
Du bist hier derjenige, der einen Linux-Flame draus macht.

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