Sicher? Sollte 2 sein, nicht 3.int Bsp5 = 3/2*2; // wir 3 gespeichert?
Sicher? Sollte 2 sein, nicht 3.int Bsp5 = 3/2*2; // wir 3 gespeichert?
Vorsicht!
Die Auflösung des Literals wird vom Precompiler übernommen.
Für das Fragment:
int main (void)
{
int8_t test = 3.1415/2 *2;
if (test == 3)
SetLED2();
bekomme ich vom Compiler im AVR-GCC weder eine Warnung, noch einen Fehler. Im Listing sehe ich aber:
000028b6 <main>:
static inline void SetLED2()
{
PORTD.OUTSET = 0x02; }
28b6: c0 e6 ldi r28, 0x60 ; 96
28b8: d6 e0 ldi r29, 0x06 ; 6
28ba: 12 e0 ldi r17, 0x02 ; 2
28bc: 1d 83 std Y+5, r17 ; 0x05
Da wird also weder eine Variable angelegt, noch im ganzzahligen Bereich, wie auf der eigentlichen Maschine, gerechnet.
Insofern sind die oben angegebenen Beispielzeilen nicht wirklich tauglich, die Sache zu durchschauen.
Besser (so, wie erwartet) wird's mit:
int main (void)
{
int8_t test = 3.1415;
test/=2;
test*=2;
if (test == 3)
SetLED2();
Hier castet sich der fraktale Anteil im Precompiler weg:
test = 3.1415 ->3
test /= 2 ->1
test *= 2 ->2
Es wird vom Compiler im Listing zwar immer noch keine Variable angelegt, aber der Aufruf von SetLED2() kommt auch nicht mehr.
Geändert von Holomino (09.05.2020 um 15:43 Uhr)
Wenn du mit Precompiler Präprozessor meinst, der rechnet nicht. GCC hat keinen Precompiler für C/C++. Die Auswertung der Literale erfolgt im Compiler.
Bei int t = 3.1415/2 *2 ist 3.1415 ein float und 2 ein int, damit ist das Ergebnis aus 3.1415/2 ein float, damit ist das 3.1415/2 * 2 auch ein float. Das wird dann zum int (3) gecastet.
Bei int u = 3/2 *2 sind 3 und 2 int, damit ist 3/2 ein int (1), damit ist 1*2 ein int (2). Das braucht nicht mehr gecastet werden.
Regeln-fuer-Konvertierungen-und-Casts
ja, stimmt ntl!
output:Code:void setup() { Serial.begin(115200); delay(1000); Serial.println(); int x=3; int y=2; int z=2; int Bsp5 = 3/2*2; Serial.println(Bsp5); Bsp5 = x/y*z; Serial.println(Bsp5); } void loop() { }
edit: sollte durchgestrichen sein, aber Durchstreichfunktion existiert hier nicht: [s]da es alles Konstanten sind, wird die "Berechnung" evtl vom Preprozessor erledigt, ohne Compiler[/s]
2
2
Aber auch mit volatile int kommt erwartungsgemäß dasselbe Ergebnis.
Code:void setup() { Serial.begin(115200); delay(1000); Serial.println(); volatile int x=3; volatile int y=2; volatile int z=2; volatile int Bsp5 = 3/2*2; Serial.println(Bsp5); Bsp5 = x/y*z; Serial.println(Bsp5); } void loop() { }
Geändert von HaWe (10.05.2020 um 14:57 Uhr)
Der Präprozessor rechnet nicht. Er bearbeitet Anweisungen zum Einfügen von Quelltext (#include), zum Ersetzen von Makros (#define), und bedingter Übersetzung (#if).
Das Makro CELSIUS_ZU_FAHRENHEIT beschreibt die Umrechnung einer Temperatur (angegeben als Parameter t) aus der Celsius- in die Fahrenheit-Skala. Auch ein Makro mit Parametern wird im Quelltext ersetzt:Code:#define CELSIUS_ZU_FAHRENHEIT( t ) ( ( t ) * 1.8 + 32 )
wird durch den C-Präprozessor ersetzt zu:Code:int fahrenheit, celsius = 10; fahrenheit = CELSIUS_ZU_FAHRENHEIT( celsius + 5 );
QuelleCode:int fahrenheit, celsius = 10; fahrenheit = ( ( celsius + 5 ) * 1.8 + 32 );
Danach darf der Compiler gemäß der spezifizierten Rechenregeln weitermachen.
Lesezeichen