www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik C-codezeile interpretieren


Autor: miki (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was genau macht diese Codezeile:
 unsigned int x;
 int y;
 x=((y*32768) >> 16);

kann es sein, dass hier eine Konversion einer negativen Zahl in eine 
positive Zahl stattfindet, sofern y negativ ist?

mfg miki

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
 
int y;
 x=((y*32768) >> 16);

Halte ich für Unsinn.

(y*32768) multipliziert y mit 32768. Aber: y kann nur Zahlenwerte 
zwischen -32768..+32767 annehmen.
(...)>>16
teilt das was in der Klammer steht durch 65536 (2hoch16)

Ich würde sagen, es kommt (unabhängig von y) immer x=0 raus.

Autor: Jörg X. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> kann es sein, dass hier eine Konversion einer negativen Zahl in eine
> positive Zahl stattfindet, sofern y negativ ist?
Kann immer passieren wenn man einer unsigned-Variablen einen signed Wert 
zuweist (Stichw.: Zweierkomplement).

hth. Jörg
ps.: die Zeile heißt allerdings effektiv :
  unsigned x;
  int y;
  x = y >> 1;

Autor: Jörg X. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@lippy:
wenn du 16Bit-ints annimmst ist 32768 aber schon ein long und y*32768 
wird nach long gewandelt

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Jörg X. (Gast)

Ja. da wirst du wohl recht haben

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jörg X. wrote:

> ps.: die Zeile heißt allerdings effektiv :
>
>   unsigned x;
>   int y;
>   x = y >> 1;
> 

Nein. Das tut sie nur dann, wenn es zu keinem Überlauf kommt und das MSB 
nicht gesetzt wird durch den Shift: da y signed ist, zeiht das 
Reschtsschieben von y das MSB nach.

Unsinn ist sowas nicht unbedingt, könnte zB aus nem Code-Generator 
rauskommen oder nach Makro-Expansion entstanden sein. Zudem ist nicht 
über sizeof(int) gesagt.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jörg X. wrote:
> @lippy:
> wenn du 16Bit-ints annimmst ist 32768 aber schon ein long

Nein, es ist unsigned int.  GCC spuckt dafür auch eine Warnung aus
(irgendwas mit "constant is so long that it is unsigned" oder so).

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>> wenn du 16Bit-ints annimmst ist 32768 aber schon ein long
>
> Nein, es ist unsigned int.

Sicher? Ich dachte, Integer-Konstanten ohne "u" am Ende seien immer
signed. Ich bin jetzt zu faul, im Standard nachzuschlagen, aber der
AVR-GCC behauptet:

  sizeof 32768  ist 4
  sizeof 32768u ist 2
  sizeof 65536u ist 4

Also scheinen Werte ab 32768 tatsächlich long zu sein, entsprechend
sind Werte ab 65536u unsigned long.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
yalu wrote:
>>> wenn du 16Bit-ints annimmst ist 32768 aber schon ein long
>>
>> Nein, es ist unsigned int.
>
> Sicher? Ich dachte, Integer-Konstanten ohne "u" am Ende seien immer
> signed.

Ah, hast Recht, oder: jein.  Dezimale Konstanten sind immer signed.
Nur bei oktalen und hexadezimalen Konstanten wird ein unsigned-Typ
benutzt, wenn der entsprechende signed-Typ nicht mehr zur Darstellung
ausreicht.

Autor: Hans (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Vorsicht! Jede Konstante ohne suffix ist immer "signed int", egal ob 
Decimal, Hex oder Octal, s. ISO Beschreibung. Und weiter gilt noch die 
"integer promotion" Regel:
....
If an int can represent all values of the original type, the value is 
converted to an int; otherwise, it is converted to an unsigned int. 
These are called the integer
promotions.48) All other types are unchanged by the integer promotions.
.....
‘‘integer promotions’’ require that the abstract machine promote the 
value of each variable to int size and then add the two ints and 
truncate the sum. Provided the addition of two chars can be done without 
overflow, or with  overflow wrapping silently to produce the correct 
result, the actual execution need only produce the same result, possibly 
omitting the promotions.

Beispiel:
char c1, c2, c3;
...
c1 = c2 + c3;

Ganz nach ISO (wie z.B. die RISC Prozessoren) Compiler macht davon:
   c1 = (char)( (int)c2 + (int)c3 );

Und ganz unsauber ist signed und unsigned Operands zusammen mischen.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hans wrote:
> Vorsicht! Jede Konstante ohne suffix ist immer "signed int", egal ob
> Decimal, Hex oder Octal, s. ISO Beschreibung.

Nein, ebendiese Beschreibung besagt, dass eine oktale oder dezimale
Konstante "unsigned int" wird, falls sie nicht als "signed int"
represäntierbar ist.  Nur dezimale Konstanten sind immer vorzeichen-
behaftet, sie wandern sofort von "int" nach "long int", wenn's nicht
mehr passt.  Damit ist 32768 vom Typ "long int", aber 0x8000 ist
"unsigned int".

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.