Forum: Compiler & IDEs wie geht der Compiler mit folgendem Ausdruck um?


von technikus (Gast)


Lesenswert?

Hallo,

ich habe ein Verständnisproblem und bitte daher um eure Hilfe.

Es geht um folgende Codezeile:
1
phase.value16=phase.value16+DEGREE_180-(2*(phase.value16-DEGREE_90));

phase.value16 ist ein unsigned int 16 aus einer union. Das 
Gesamtergebnis der Formel ist immer positiv.
Doch wie geht der Compiler mit
1
(2*(phase.value16-DEGREE_90))

um, wenn das Ergebnis in der Klammer negativ ist? Anders gefragt, kann 
das Ergebnis negativ sein wenn mit unsigned Variablen gearbeitet wird?

Z.B.
1
#define DEGREE_90   512
2
#define DEGREE_180  1024
3
phase.value16=0;
4
5
(2*(phase.value16-DEGREE_90))

ist das Ergebis der Klammer dann -1024 ?

Also das Gesamtergebnis
1
phase.value16 = 0 + DEGREE_180-(2*(phase.value16-DEGREE_90));

phase.value16 == 0 ???


Ich hoffe das ich mich einigermaßen verständlich ausgedrückt habe.

Gruß
Ernst

AVR GCC mit AVR Studio

von Stefan E. (sternst)


Lesenswert?

technikus schrieb:

> Anders gefragt, kann
> das Ergebnis negativ sein wenn mit unsigned Variablen gearbeitet wird?

Nein.

1
> #define DEGREE_90   512
2
> #define DEGREE_180  1024
3
> phase.value16=0;
4
> 
5
> (2*(phase.value16-DEGREE_90))
6
>
>
> ist das Ergebis der Klammer dann -1024 ?

Nein, 64512.

> Also das Gesamtergebnis
>
1
> phase.value16 = 0 + DEGREE_180-(2*(phase.value16-DEGREE_90));
>
> phase.value16 == 0 ???

Nein, 2048.
Aber auch bei -1024 in der Klammer wäre das Ergebnis doch 2048. Wie 
kommst du auf 0?

von Zabriskie (Gast)


Lesenswert?

Vorsicht mit implizitem Typecasting! Es kann sein, dass der compiler das 
DEGREE_90 als erstes als signed int liest und dann für die Variable ein 
implizites Typecasting auf signed durchführt.

Deshalb am besten in solchen Fällen im Zweifelsfall immer sowas wie

(2*(phase.value16-(unsigned int)DEGREE_90))

schreiben. Bin mir gerade nicht sicher, was er mit einer negativen Zahl 
als Zuweisung macht. Könnte mir vorstellen, das das einen Überlauf gibt 
oder vielleicht NaN, wenn das wie bei Floating Point vorgesehen ist, 
aber keine Ahnung.

von Stefan E. (sternst)


Lesenswert?

Zabriskie schrieb:
> Es kann sein, dass der compiler das DEGREE_90 als erstes als signed int
> liest

Was heißt hier "kann sein"? DEGREE_90 ist ein signed int.

> und dann für die Variable ein
> implizites Typecasting auf signed durchführt.

Nö, unsigned "gewinnt".

von Hc Z. (mizch)


Lesenswert?

Anders ausgedrückt:  unsigned ist der "höhere" Typ; eine implizite 
Konversion von unsigned int nach int kann NIE stattfinden.

von Zabriskie (Gast)


Lesenswert?

Im Prinzip (und praktisch) habt Ihr Recht, aber

Stefan Ernst schrieb:
> Zabriskie schrieb:
>> Es kann sein, dass der compiler das DEGREE_90 als erstes als signed int
>> liest
>
> Was heißt hier "kann sein"? DEGREE_90 ist ein signed int.

<Klugscheißermodus>
Nö :). Da würde ich gerne mal den C Standard zu sehen.

unsuffixed decimal   int, long int, C only long long int

http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=/com.ibm.xlcpp8a.doc/language/ref/conref.htm

Der Typ von numerischen literals hängt demnach von der Interpretation 
der Umgebung durch den Compiler ab (Ok unsigned int ist es nicht). Ich 
erwähne das nur, weil ich schonmal über den Unterschied zwischen "5." 
und "5" gestolpert bin.

</Klugscheißermodus>

von Stefan E. (sternst)


Lesenswert?

Zabriskie schrieb:

> Da würde ich gerne mal den C Standard zu sehen.
1
The type of an integer constant is the first of the corresponding list
2
in which its value can be represented.
3
4
Suffix | Decimal Constant | Octal or Hexadecimal Constant
5
------+------------------+------------------------------
6
none  | int              | int
7
      | long int         | unsigned int
8
      | long long int    | long int
9
      |                  | unsigned long int
10
      |                  | long long int
11
      |                  | unsigned long long int
12
------+------------------+------------------------------
Ergo ist es ein int (was identisch zu signed int ist).

> Der Typ von numerischen literals hängt demnach von der Interpretation
> der Umgebung durch den Compiler ab (Ok unsigned int ist es nicht).

Der Standard ist da eindeutig, da gibt es keinen 
Interpretationsspielraum.

> Ich erwähne das nur, weil ich schonmal über den Unterschied zwischen
> "5." und "5" gestolpert bin.

Das ist ja nun wieder eine ganz andere "Baustelle".

von technikus (Gast)


Lesenswert?

Stefan Ernst schrieb:
> Nein, 2048.
> Aber auch bei -1024 in der Klammer wäre das Ergebnis doch 2048. Wie
> kommst du auf 0?

Fehler - ich meinte 2048

Vielen Dank für die aufschlussreichen Antworten

Gruß
Ernst

von Zabriskie (Gast)


Lesenswert?

technikus schrieb:
> Vielen Dank für die aufschlussreichen Antworten

Ebenfalls Danke für die Richtigstellung Stefan. Demnach muss man sich 
erst ab 32768 Sorgen machen (bei einer garantierten Länge von int von 16 
bit).

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.