Hallo
Einer von Euch Cracks kann mir sicher sagen, unter welchem Stichwort ich
das folgende Probleme suchen kann:
Warum wird beim ersten Program der IF nicht wahr aber beim zweiten sehr
wohl ?
1
#include<stdio.h>
2
3
intmain(void)
4
{
5
unsignedcharday,wday;
6
7
day=1;
8
wday=5;
9
10
if((day-wday)>=25)
11
{
12
printf("In IF\n");
13
}
14
}
und mit "unsigned int" anstatt "unsigned char":
1
#include<stdio.h>
2
3
intmain(void)
4
{
5
unsignedintday,wday;
6
7
day=1;
8
wday=5;
9
10
if((day-wday)>=25)
11
{
12
printf("In IF\n");
13
}
14
}
Wird bei einer solchen Rechnung nicht zuerst das Resultat errechnet,
also -4 und dieses dann über das 2'er Komplement in eine vorzeichenlose
Zahl umgewandelt ?
Bei char also 256 - 2 = 252 und bei int (32bit) 2,147,483,647 - 4. Also
beides sehr hohe Zahlen, und somit sollte der IF doch immer wahr werden
?
Ich habe da wohl noch etwas nicht begriffen ;-)
Danke für die Nachhilfe.
Daniel
Umgebung: gcc 4.7.2 unter 32bit Linux und gcc 4.6.1 für ARM-Cortex M4
Und scheinbar: ushort - ushort auch int ?, denn hier wird der if auch
nicht wahr.
In welcher Lektüre finde ich das, meine C-Bücher schweigen sich hier aus
(oder ich finde es nicht darin...)?
Daniel B. schrieb:> In welcher Lektüre finde ich das, meine C-Bücher schweigen sich hier aus> (oder ich finde es nicht darin...)?
Garantiert Letzteres. Oder die Bücher taugen nur für den Kachelofen.
English passt auch, danke und Deine erweiterte erste Anwort erklärt
alles.
Somit ist also ein solcher Vergleich mit uchar völlig korrekt, auch wenn
er sich einem nicht so erfahrenen C-Programmierer nicht auf Anhieb
erschliesst ? Eigentlich wäre da ein Verwenden von int angebrachter,
braucht aber natürlich auch mehr Speicher.
In eneglischsprachiger Literatur könnte man im Stichwortregister auch
mal unter "Integer Promotion" bzw. nach "Promotion rules" suchen.
Und ja. Die sind wichtig. Ein Buch, in dem die nicht vorkommen, taugt
nicht viel.
>Eigentlich wäre da ein Verwenden von int angebrachter,>braucht aber natürlich auch mehr Speicher.
Oder mit einer u8 Hilfsvarable. Ich bin letzten auchdarüber gestolpert..
Daniel B. schrieb:> English passt auch, danke und Deine erweiterte erste Anwort erklärt> alles.>> Somit ist also ein solcher Vergleich mit uchar völlig korrekt
ist er.
> erschliesst ? Eigentlich wäre da ein Verwenden von int angebrachter,
Nicht wirklich.
Der Knackpunkt ist ein anderer.
Der Knackpunkt besteht darin, dass bei der Promotion ein niedrigerer
Datentyp in einen höheren Datentyp gewandelt wird, SOFERN dieser alle
darstellbaren Werte des niedrigeren Datentyps ebenfalls darstellen kann.
Du hast einen unsigned char. Der wird für die Rechnerei implizit auf
einen int hochgecastet, WEIL ein int alle Werte eines unsigned char
(0..255) aufnehmen kann. Und über diesen Umweg kriegen die Werte wieder
ein Vorzeichen, welches dann in die Berechnung eingeht.
Wären die Werte von vorneherein schon ein unsigned int gewesen, dann
würde dieser Schritt nicht passieren.
Daher:
if (((unsigned int)day - wday) >= 25)
und dein Vergleich funktioniert wieder, wie gewünscht.
Das 'Problem' an dieser Stelle ist der Vergleich, der das Vorzeichen
mitberücksichtigt. Hättest du dieses hier gemacht
unsigned char diff = day - week;
dann würde zwar konzeptionell wieder dieselbe Promotion ablaufen, aber
da das Ergebnis wieder einem unsigned char zugewiesen wird, verflüchtigt
sich das zwischenzeitliche Vorzeichen wieder ohne Schaden zu
hinterlassen
if( diff >= 25 )
funktioniert dann wie erwartet.
Die "Promotion rules" habe ich sogar gefunden, aber wohl gerade die
falsche Seite, oder sie nicht begriffen (wohl auch hier letzteres...)
"http://de.wikipedia.org/wiki/Promotion_(Typumwandlung)"
Dort wird uchar -> ushort -> uint und da war ich wieder bei meinem
Problem.
Aber danke Jungs, super Erklärungen.
Btw, das Codeteil ist aus der Sommerzeitroutine von Peter Dannegger, und
ein Crack wie er weiss natürlich was er macht, mir hat es sich aber beim
Studium des Codes nicht erschlossen.
Daniel B. schrieb:> Die "Promotion rules" habe ich sogar gefunden, aber wohl gerade die> falsche Seite, oder sie nicht begriffen (wohl auch hier letzteres...)>> "http://de.wikipedia.org/wiki/Promotion_(Typumwandlung)">> Dort wird uchar -> ushort -> uint und da war ich wieder bei meinem> Problem.
Das erscheint mir falsch. Außerdem verstehe ich nicht, warum die
Promotion hier in zwei Schritten ablaufen sollte. In der C99-Definition
steht:
***********************************************************************
The following may be used in an expression wherever an int or unsigned
int may be used:
— An object or expression with an integer type whose integer conversion
rank is less than the rank of int and unsigned int.
— A bit-field of type _Bool, int, signed int, or unsigned int.
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.
***********************************************************************
und:
***********************************************************************
— The rank of long long int shall be greater than the rank of long int,
which shall be greater than the rank of int, which shall be greater than
the rank of short int, which shall be greater than the rank of signed
char.
— The rank of any unsigned integer type shall equal the rank of the
corresponding signed integer type, if any.
***********************************************************************
Also mit anderen Worten: Alles, was kleiner ist, als int, wird erstmal
zu int promoted, sofern es reinpaßt.
Daniel B. schrieb:> Btw, das Codeteil ist aus der Sommerzeitroutine von Peter Dannegger, und> ein Crack wie er weiss natürlich was er macht, mir hat es sich aber beim> Studium des Codes nicht erschlossen.
Die int-Promotion ist hier natürlich richtig, da ja die Umschaltung
frühestens am 25.3. erfolgen darf.
Beim unsigned Vergleich könnte ja schon am 1.3. Sommerzeit sein.
So ist es besser verstehbar:
Hehe, was meinst Du warum ich auf das Ganze gekommen bin ;-)
Meine neue grosse NTP-gesteuerte 7-Segment-LED Uhr an der Wand hat
sauber am 1 und 2. März auf Sommerzeit gestellt.
Also Code untersucht, und rausgefunden, dass ich meinen, zuerst selber
entwickelten Code mit Teilen von Deinem "Time.c" ergänzt habe, dabei
aber versehentlich uint Variablen verwendet habe...
Sehr schön, habe ich wieder mal was gelernt.