Steven () schrieb:> gibt es etwas, womit man Folgendes vereinfachen kann.
Da geht nix zu vereinfachen. Eigentlich ist es schon zu sehr
vereinfacht, denn wie ein bool den Wert true intern repräsentiert, ist
nicht einheitlich festgelegt, festgelegt ist nur, daß die binäre
Repräsentation von true von 0 verschieden sein muß.
Es kann also gut passieren, dass es einen Compiler gibt, der den Code
zwar übersetzt, aber trotzdem zur Laufzeit ein falsches Ergebnis
produziert.
Richtig wäre also folgendes:
if (temp)
{
PORTA = (PORTA | (1<<PA0));
}
else
{
PORTA = (PORTA & ~(1<<PA0));
}
> Gerne auch was in ASM.
Da hast du exakt das gleiche Problem mit den bool. Dementsprechend müßte
man auch in Asm auf !=0 prüfen und dann entsprechend des Ergebnisses
verzweigen. Käme also in etwa sowas raus:
lds reg,temp ;2 2
tst reg ;1 1
breq PC+2 ;1 2
sbi PORTA,PORTA0 ;2
brne PC+2 ;2 1
cbi PORTA,PORTA0 ; 2
;- -
8 8
c-hater schrieb:> Da geht nix zu vereinfachen. Eigentlich ist es schon zu sehr> vereinfacht, denn wie ein bool den Wert true intern repräsentiert, ist> nicht einheitlich festgelegt, festgelegt ist nur, daß die binäre> Repräsentation von true von 0 verschieden sein muß.
Die interessiert aber nicht. Es interessiert, was rauskommt, wenn der
bool in einen int konvertiert wird, und das ist sehr wohl festgelegt.
Rolf Magnus schrieb:> Die interessiert aber nicht. Es interessiert, was rauskommt, wenn der> bool in einen int konvertiert wird, und das ist sehr wohl festgelegt.
Den Typ Boolean gibt es in C nicht. Also kann da auch nichts konvertiert
werden. Das Ergebnis einer Vergleiches ist immer Integer. Ungleich ist
0, Gleich ist nicht 0, üblicherweise 1.
Dennoch ist das
1
#define FALSE 0
2
#define TRUE 1
falsch, sondern es muss heissen
1
#define FALSE 0
2
#define TRUE !0
Und das interessiert sehr wohl. Insbesondere in Anfängerprogrammen, wenn
eine Abfrage if(x == 1) lautet, macht das Programm meistens nicht das,
was es soll.
mfg.
Max H. schrieb:> Ich wusste gar nicht dass es in C so etwas wie bool gibt.
In C gibt es Alles:
#include <Halsbonbon.h>
#include <Lockenwickler.h>
;-)
MfG Paul
#define Power_set(x) Power_out_PORT = (Power_out_PORT & ~(1<<Power_outpin)) | (!(x)<<Power_outpin); //x=true power on; x=false power off
2
Power_set(true);//hier optmiert er zu CBI
Und "übergebe" ich eine Variable führt er die entsprechenden Operationen
aus. (selbstverständlich)
Optimieren lässt sich da wirklich nix.
In Assembler lässt sich auch nicht viel sparen.
Bei dem Code von C-Hater ließen sich noch zwei Taktzyklen sparen...
Gruß
Steven
Thomas Eckmann schrieb:> Rolf Magnus schrieb:>> Die interessiert aber nicht. Es interessiert, was rauskommt, wenn der>> bool in einen int konvertiert wird, und das ist sehr wohl festgelegt.>> Den Typ Boolean gibt es in C nicht. Also kann da auch nichts konvertiert> werden. Das Ergebnis einer Vergleiches ist immer Integer. Ungleich ist> 0, Gleich ist nicht 0, üblicherweise 1.
In C99 (ISO 9899) existiert der Typ Boolean, er heisst _Bool. bool ist
ein Makro, dass auf ihn aufgelöst wird.
Er muss mindestens die Werte 0 und 1 aufnehmen können.
Eine Konversion von einem skalaren Datentyp in bool ergibt genau dann 0,
wenn der Skalar 0 ist und 1 in jedem anderen Fall.
Daher muss nach C99
1
#define TRUE 1
2
3
intwert=99;
4
boolistNull=wert;
5
if(istNull==TRUE)
6
printf("Doh!");
7
else
8
printf("Donuts!");
ein Doh! ausgeben.
Warum?
Ich zitiere mal C99:
> 6.3.1.2 Boolean type> 1 When any scalar value is converted to _Bool, the result is 0 if the> value compares equal to 0; otherwise, the result is 1
Es gilt also bei bool istNull = wert ; der "otherwise" Fall. istNull ist
daher 1.
Der Werte Vergleich 1 == 1 ist daher wahr und printf("Doh!")
auszuführen.
Du siehst, ich kann durchaus einen boolean mit 1 vergleichen und bekomme
immer das richtige Ergebnis.
Allerdings, und da ist das Problem mit den makros TRUE und FALSE
besonders in der WinAPI: wird das Ergebnis nicht als bool sondern als
anderer Skalar geliefert, so ist das Ergebnis ein Anderes, wie leicht zu
sehen, wenn man die casts explizit aufschreibt:
Tim Seidel schrieb:> #define TRUE 1>> int wert = 99 ;> bool istNull = wert ;> if (istNull == TRUE)
Aber if(wert == TRUE) geht schief. Darum geht es. Denn das liest man in
Anfängerprogrammen mindestens einmal die Woche.
Dafür hättest du aber nicht nach dem C-Standard googeln müssen.
und sowas
1
intwert=99;
2
boolistNull=wert;
3
if(istNull==TRUE)
sieht man höchstens in einer Klausur.
Um einen Integer auf 1 zu zwingen macht man sowas: !!wert.
Willkommen in der Realität.
mfg.
Thomas Eckmann schrieb:> Tim Seidel schrieb:>> #define TRUE 1>>>> int wert = 99 ;>> bool istNull = wert ;>> if (istNull == TRUE)>> Aber if(wert == TRUE) geht schief. Darum geht es. Denn das liest man in> Anfängerprogrammen mindestens einmal die Woche.>> Dafür hättest du aber nicht nach dem C-Standard googeln müssen.>> und sowas> int wert = 99 ;> bool istNull = wert ;> if (istNull == TRUE)>> sieht man höchstens in einer Klausur.
Ich nehme also an, du kennst die Realität aus der Uni. Also HiWi oder
Dozent.
Das oben genannte Konstrukt ist durchaus üblich und abseits der Klausur
relevant. Ich kann dir das "eingekochte Beispiel" auch anders aufbauen:
1
boolGetEigenschaft(...)
2
{
3
...
4
return(zwischenErgebnis&0xDEADBEEF);
5
}
6
7
8
if(1==PruefeEigenschaft(...))
9
...
Copy & Paste bei der nächsten Eigenschaft, die aber dann nicht bool
sondern int liefert und schon hast du beide Fälle in einem Code.
Um nicht in diese Fallen zu laufen vermeidet man i.d.R. dies durch
Strukturvorgaben. In C und in vielen Anwendungen wirst du dennoch auf
diese Probleme stoßen und mit Sicherheit auf den ein oder anderen
Programmierer, der die Problematik nicht verstanden hat.
Nicht umsonst gibt man z.B. mit MISRA viele Vorgaben, die solche
Unachtsamkeiten vermeiden sollen.
> Um einen Integer auf 1 zu zwingen macht man sowas: !!wert.>> Willkommen in der Realität.>> mfg.
Macht man mit Sicherheit nicht. Da würd ich 1 nehmen ;-)
Aber ich weiss worauf du hinaus willst. Das jedoch ist ebenfalls zu kurz
gedacht für diese Art der "Arbeitsoptimierung"
Das Programm wird nicht günstiger, schneller oder wartbarer, wenn ich
weniger Zeichen im Quellcode nutze ;-)
Wenn ich ein bool haben will mach ich eins daraus (cast). Wenn ich eine
Wertebereichsbeschränkung haben will nutze ich das einmal vor 20 Jahren
hingetackerte CROP(wert, min, max) Makro mit deutlich größerer
Lesbarkeit und Flexibilität.
Thomas Eckmann schrieb:>> if (istNull == TRUE)>> Aber if(wert == TRUE) geht schief. Darum geht es. Denn das liest man in> Anfängerprogrammen mindestens einmal die Woche.
Die vernünftigste Lösung ist es, den Satz
"In C ist weniger oft mehr"
ernst zu nehmen und
1
if(istNull)
zu schreiben.
istNull ist bereits als boolscher Wert gedacht. Der ist bereits "TRUE"
oder "FALSE" (im Sinne der logischen Definition von TRUE und FALSE). Es
gibt daher keinen wirklichen Grund, das noch mal mit TRUE zu
vergleichen.
Man schreibt ja auch nicht
1
if((i>5)==TRUE)
wenn etwas bereits ein boolscher Wert ist, dann wird der direkt
verwendet. In der Negierung noch mit einem ! davor, aber das wars dann
auch schon
1
if(istNull)
2
...
3
4
if(!istNull)
5
....
mit diesen doppelt gemoppelten expliziten Vergleichen auf TRUE oder
FALSE schiesst man sich nur ins eigene Knie.
c-hater schrieb:> Richtig wäre also folgendes:>> if (temp)> {> PORTA = (PORTA | (1<<PA0));> }> else> {> PORTA = (PORTA & ~(1<<PA0));> }
Ganz genau. Das ist nicht nur am besten lesbar, sondern wird auch zu
schnellerem Code:
1
$cattest.c
2
#include<avr/io.h>
3
#include<stdbool.h>
4
5
voidf1(boolx)
6
{
7
PORTC=(PORTC&~(1<<PC0))|(x<<PC0);
8
}
9
10
voidf2(boolx)
11
{
12
if(x)PORTC=PORTC|(1<<PC0);
13
elsePORTC=PORTC&~(1<<PC0);
14
}
Compilieren mit
1
avr-gcc -c -mmcu=atmega8 -save-temps -Os test.c
Und jetzt schauen wir uns test.s an. Funktion f1() wird in allen
Optimierungsstufen so übersetzt:
1
in r25,0x15
2
andi r25,lo8(-2)
3
or r25,r24
4
out 0x15,r25
5
ret
allerdings nur, so lange wir PC0 verwenden. Für andere Portbits muß der
bool in r24 erst umgerechnet werden. Für PC3 kommt z.B. das raus;
1
in r18,0x15
2
ldi r19,lo8(8)
3
mul r24,r19
4
movw r24,r0
5
clr __zero_reg__
6
andi r18,lo8(-9)
7
or r18,r24
8
out 0x15,r18
9
ret
Funktion f2() hingegen kommt so raus (mit -O, -O1, -Os)
1
tst r24
2
breq .L5
3
sbi 0x15,0
4
ret
5
.L5:
6
cbi 0x15,0
7
ret
In den Optimierungsstufen -O2 und höher hingegen so:
1
cpse r24,__zero_reg__
2
rjmp .L8
3
cbi 0x15,0
4
ret
5
.L8:
6
sbi 0x15,0
7
ret
Ein anderes Portbit in f2() führt lediglich zu einer anderen Bitnummer
in den sbi bzw. cbi Befehlen.
Merksatz: Code der in C kompakt aussieht, wird deswegen noch lange nicht
zu kompaktem Maschinencode.
XL
Tim Seidel schrieb:> Ich nehme also an, du kennst die Realität aus der Uni. Also HiWi oder> Dozent.
Man muss schon ziemlich beschränkt sein, um das daraus zu schliesen:
>> sieht man höchstens in einer Klausur.
Du kannst noch so viel mit dem Standard wedeln.
Sowas "if((bool)x== TRUE)" macht niemand. Jedenfalls nicht freiwillig.
Und falls doch, brauchst du dem nur die Drogen wegzunehmen.
mfg.
Thomas Eckmann schrieb:> Sowas "if((bool)x== TRUE)" macht niemand. Jedenfalls nicht freiwillig.> Und falls doch, brauchst du dem nur die Drogen wegzunehmen.
Und stattdessen Alkohol geben. Trifft man den richtigen Pegel, schreibt
man die besten Programme. Ist aber knifflig. Siehe hier:
http://xkcd.com/323/
Steven () schrieb:> In Assembler lässt sich auch nicht viel sparen.> Bei dem Code von C-Hater ließen sich noch zwei Taktzyklen sparen...
Wie?
Eigentlich nur, indem man irgendwas voraussetzt, was für den allgemeinen
Fall nicht vorausgesetzt werden kann.
Max H. schrieb:> Steven () schrieb:>> es geht um C>> Ich wusste gar nicht dass es in C so etwas wie bool gibt.
Dann ist dein Wissen aber aber auf einem ziemlich alten Stand. Das ist
in C nämlich seit 15 Jahren schon Standard.
Thomas Eckmann schrieb:> Den Typ Boolean gibt es in C nicht.
Und noch einer auf dem Stand vom letzten Jahrtausend.
Thomas Eckmann schrieb:> Um einen Integer auf 1 zu zwingen macht man sowas: !!wert.>> Willkommen in der Realität.
Sowas habe ich bisher immer nur als Antwort gesehen, wenn jemand gefragt
hat, wie "man" das macht. In der Realität, also echten Programmen, aber
noch nicht. Da dann höchstens: wert ? 1 : 0. Das finde ich auch besser
lesbar als die doppelte Invertierung.
c-hater schrieb:> denn wie ein bool den Wert true intern repräsentiert, ist> nicht einheitlich festgelegt, festgelegt ist nur, daß die binäre> Repräsentation von true von 0 verschieden sein muß.
true ist 1
1
C99 7.16
2
3
1 The header <stdbool.h> defines four macros.
4
2 The macro "bool" expands to "_Bool".
5
3 The remaining three macros are suitable for use in #if
6
preprocessing directives. They are "true" which expands
7
to the integer constant 1, "false" which expands to the
8
integer constant 0, and [...]
_Bool wiederum ist in C99 ein Typ:
1
C99 6.3.1.2 Boolean type
2
3
1 When any scalar value is converted to _Bool, the result
4
is 0 if the value compares equal to 0; otherwise,
5
the result is 1.
Thomas Eckmann schrieb:> Den Typ Boolean gibt es in C nicht.
Siehe oben, auch wenn das Schlüsselwort nicht "Boolean" lautet.
> Dennoch ist das>
1
>#defineFALSE0
2
>#defineTRUE1
3
>
>> falsch, sondern es muss heissen>
1
>#defineFALSE0
2
>#defineTRUE!0
3
>
!0 war in C schon immer 1:
1
C99 6.5.3.3 Unary arithmetic operators
2
3
5 The result of the logical negation operator ! is 0 if the
4
value of its operand compares unequal to 0, 1 if the value
5
of its operand compares equal to 0. The result has type int.
Version #2 ist nur Zucker, mehr nicht. Und beide sind schlechter Stil da
es true und false gibt, denn der OP schreibt offenbar in C99+.