float zu unsigned int: Verhalten bei negativen Zahlen

Gast #5218524
Lesenswert?

Ich habe folgendes Stück Code, das mit einem GCC 4.6.3 kompiliert wird. 
GetValue() liefert als Rückgabewert einen float.
1
unsigned long helper;
2
float value;
3

4
value = GetValue();
5

6
helper = (value * 1000);
Muss ich damit rechnen, dass das Vorzeichen abgeschnitten wird und der 
Inhalt von 'helper' immer positiv ist?
Gast #5218565
Lesenswert?

Das Ergebnis ist nicht definiert für negative Zahlen, weil die 
Darstellung negativer signed integer nicht festgelegt ist. Es wird schon 
irgendein Bitmuster herauskommen, das als unsigned integer interpretiert 
dann natürlich positiv ist. Höchstwahrscheinlich wird aber z.B. eine 
-2.0 nicht als 2 enden.
Moderator #5218778
Lesenswert?

Wie Nop schon geschrieben hat, ist das Ergebnis undefiniert. In der
ISO-Norm kannst du das nachlesen:

1
When a finite value of real floating type is converted to an integer
2
type other than _Bool, the fractional part is discarded (i.e., the value
3
is truncated toward zero). If the value of the integral part cannot be
4
represented by the integer type, the behavior is undefined.

Der GCC scheint in solchen Fällen den nächstliegenden darstellbaren Wert
zu nehmen. Bei der Konvertierung eines negativen double oder float in
ein unsigned int ist dieser immer 0.
Gast #5218790
Lesenswert?

Man könnte vielleicht Yalus Gedanken so weiterführen:

Falls ein bestimmtes Verhalten undefiniert ist, dann ist es nützlich, 
das erwünschte Verhalten ausdrücklich als Code hin zu schreiben. Das hat 
zwei positive Effekte.

1. und ganz offensichtlich, wird eben genau das erwünschte Verhalten 
erreicht. Und zwar nichts Anderes und definitiv und mit absoluter 
Sicherheit.
2. Die Varianten des unterschiedlichen Compilerverhaltens in einem, dem 
Standard nach undefinierten Fall, müssen nicht jeweils erinnert und 
festgestellt werden und der Code ist ohne weiteres portabel. Es reicht 
im Code eine Bemerkung wie: "Explicitly describing conversion behaviour 
due to undefined case (converting negative floats to unsigned) from 
standard" oder sinngemäß.

Das wäre so meine Idee dazu. Hoffe, dass ist nützlich.
#5218876
Lesenswert?

Peter D. schrieb:
> Theor schrieb:
>> Falls ein bestimmtes Verhalten undefiniert ist, dann ist es nützlich,
>> das erwünschte Verhalten ausdrücklich als Code hin zu schreiben.
>
> Gute Idee.
> Z.B.:
>
1
> uint32_t convert( float val )
2
> {
3
>   if( val <= 0 )
4
>     return 0;
5
>   if( val >= (uint32_t)-1 )
6
>     return -1;
7
>   return val;
8
> }
9
>

Nö. Genau so eigentlich nicht. Undefiniertes Verhalten lässt sich nicht 
mit undefiniertem Verhalten ( (uint32_t) -1) "wegprogrammieren".

Die ISO Dokumentation empfiehlt so was, z.B.:
1
(unsigned long) fmod(fabs(rint(f)), LONG_MAX + 1.0)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren