Hallo,
ich bin recht neu, was Programmierung angeht und hätte folgende Frage:
Als Beispiel habe ich mal eine Prozentrechnung ausgesucht. Dabei ist
100% = 255 und als Ergebnis reicht mir eine Ganzzahl. Reicht es dann aus
der Variable "Ergebnis" auch nur 8 Bit zuzuweisen? Der Zwischenschritt
"Wert * Prozent" ist ja kurzzeitig größer als 255. Hier würde mich als
Grundlagenfrage interessieren, wo so ein Zwischenschritt in der
Berechnung gespeichert wird? Wäre es in der Variable, müsste ich ja die
Variable entsprechend groß planen, um keine Speicherprobleme zu
bekommen?
Mich interessiert einfach die Funktionsweise dahinter und ich möchte es
natürlich gerne richtig machen und nicht unnötigerweise meine Variablen
immer zu groß definieren. Für Google habe ich wohl nicht die richtigen
Begriffe erwischt.
So wird das nicht funktionieren. Er wird zuerst 255*80 rechnen was zu
groß ist und zu einem Überlauf führt und anschließend durch 100 teilen.
Ich bin mir Grade nicht sicher ob es da ein definiertes verhalten gibt
aber vermutlich bleibt er einfach bei 255 und teilt durch 100 oder tut
irgend was anderes was du nicht möchtest. Alternative kannst du erst
durch 100 teilen und dann mal 80 rechnen, hier wird die aber ordentlich
Präzision verloren gehen, da er die 2,55 zu 2 macht. Meiner Meinung nach
solltest du mit einem 16 Bit Wert rechnen und erst mit 80 multiplizieren
und anschließend durch 100 teilen.
Datentypen kleiner als int gibt es nur im Speicher - sobald sie aus dem
Speicher geholt werden, werden sie auf int-Größe erweitert. Gerechnet
wird also prinzipiell immer mit mindestens int-Größe. Wie groß ein int
ist, ist compilerabhängig - üblich sind 16 (bei z.B. AVR) und 32 Bit.
Das ist das, was der Compiler machen muß - der Optimizer reduziert das
evtl wieder (zu z.B. 8-Bit-Arithmetik), wenn er garantieren kann, dass
trotzdem das korrekte Ergebnis rauskommt.
GeraldB schrieb:> Kann man das nicht evtl. sicherheitshalber casten?
Casten kann man das. Aber mit welchem Sinn?
foobar schrieb:> Gerechnet wird also prinzipiell immer mit mindestens int-Größe.
Genau. Damit funktioniert die Rechnung, da int immer mindestens 16 Bit
breit ist und der Maximalwert von 255 * 100 für das Zwischenergebnis da
rein passt.
Gerald K. schrieb:> Eingabe >=100 liefert 0xff
Nein, in der Zeile
Gerald K. schrieb:> Prozent =atoi(argv[1]);
werden nur die letzten 8 Bits übernommen. Wenn man eine riesige Zahl
eingibt (z.B. 0xAAAAAA01 bei 4Bytes-Int) wo die letzten 8 Bits eine
Zahl <100 ergeben, dann wird falsch gerechnet (obwohl die eingegebene
Prozentzahl riesig ist).
Da wird tatsächlich abgeschnittet.
C wandelt beide Variablen in die größere der Variablen um und das
Ergebnis besteht ebenfalls aus diesem Typ. Bei einem 8-Bit- und einem
16-Bit-Wert werden der 8-Bit-Wert erst in 16 Bit umgewandelt und dann
gerechnet und ein 16-Bit-Wert ausgegeben. Ebenso wird bei int und float
erst in float umgewandelt, das Ergebnis ist dann auch float. Es würde
also oben im Beispiel reichen, eine Variable zu casten. Es würde nicht
reichen, die 100 auf 16 Bit zu casten, weil erst die Multiplikation
ausgeführt wird. Es mag sein, das ein Compiler grundsätzlich in int
rechnet, aber besser ist es trotzdem, explizit zu casten, dann weiß man,
was man tut und der Code bleibt portierbar.
Bernd
Bernd schrieb:> C wandelt beide Variablen in die größere der Variablen um und das> Ergebnis besteht ebenfalls aus diesem Typ.
Mindestens jedoch int. Das nennt sich in C-Sprech "integer promotion".
> Bei einem 8-Bit- und einem 16-Bit-Wert werden der 8-Bit-Wert erst in 16> Bit umgewandelt und dann gerechnet und ein 16-Bit-Wert ausgegeben.
Nur wenn int 16 Bit breit ist. Wenn der 32 Bit breit ist, werden beide
Seiten erst auf 32 Bit erweitert.
> Ebenso wird bei int und float erst in float umgewandelt, das Ergebnis ist> dann auch float.
Die genauen Regeln können aber etwas komplizierter sein. Das findet man
unter dem Begriff "usual arithmetic conversions".
> Es würde also oben im Beispiel reichen, eine Variable zu casten.
Es würde auch reichen, gar keine zu casten. Ich würde gerade einem
Anfänger raten, nur dann einen Cast einzusetzen, wenn er auch notwendig
ist und wenn man genau erklären kann, warum er notwendig ist.
> Es würde nicht reichen, die 100 auf 16 Bit zu casten,
100 ist vom Typ int und damit sowieso mindestens 16 Bit breit.
> Es mag sein, das ein Compiler grundsätzlich in int rechnet,
Jeder standardkonforme Compiler tut das.
Eine eigene Frage?
Dieser Thread ist über 5 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.