2016-06-28 22 views
1

Ich habe eine Weile debuggt, bevor ich eine meiner ganzen Zahlen als MAX (2, x) definiert fand war -4, obwohl 2 deutlich größer als -4 ist.Geschachtelte MAX bewirkt, dass bei Verwendung verschiedener Objekttypen manchmal der kleinste Wert zurückgegeben wird - MAX (a, MAX (b, c))

Hier ist eine vereinfachte Version von dem, was mein Code ausgeführt wurde, so dass Sie die Unregelmäßigkeit aus erster Hand erfahren können.

NSLog(@"a) %i", (int)MAX(2,-4)); 
    NSString *aString = @"90586381095716439405631195482586763570805293418319186736659080000000000000"; 
    int aNumber = (int)MAX(2,10-MAX(1,(aString.length/5))); 
    NSLog(@"b) %i", aNumber); 
    NSLog(@"c) %i", (int)MAX(2,10-MAX(1,16))); 

a) protokolliert 2 wie erwartet.

b) wird protokollieren -4 was für mich keinen Sinn macht.

c) wird log 2 wie erwartet (jetzt b macht noch weniger Sinn für mich)


Was bin ich nicht bekommen? MAX ist braun in xCode, was mich denken lässt, dass es irgendwo in der UIKit- oder Math-Bibliothek als CLANG gesetzt ist. Wenn das der Fall ist, wird der innere MAX erst verarbeitet, nachdem der erste MAX verarbeitet wurde und dadurch verschachtelte Fehler entstehen. Aber wenn das der Fall wäre würde c) auch nicht -4 geloggt haben?

Antwort

2

Ich benutze Objective-C nicht, aber die length der Zeichenfolge ist wahrscheinlich ein vorzeichenloser Wert. Wenn es genauso funktioniert wie die Ebene C, würde dies dazu führen, dass das Ergebnis der inneren MAX ebenfalls vorzeichenlos wird, und daher wird die Subtraktion von 10 als vorzeichenlos ausgeführt. Dies führt dazu, dass der Wert unterläuft und zu einem sehr großen Wert führt, etwa 4294967292 unter Annahme von 32-Bit-Ints, und daher wird er von der äußeren MAX gewählt.

Das letzte int ist was dann konvertiert es zurück in unterzeichnet und Sie am Ende mit einem negativen Wert. Wenn Ihr Compiler gut ist und Sie die (int) auslassen, sollten Sie eine Warnung darüber erhalten.

Moral der Geschichte, verwenden Sie keine Fremdcasts, die der Compiler Ihnen keine wertvollen Warnungen gibt.

+0

Wow, Sie haben recht, Casting '(int)' auf die string.length das Problem behoben. '(int) aString.length' - und auch im Fall c) Casting '(NSUInteger)', was .Length ist, um die '16' reproduziert das Problem. Also MAX hat Probleme mit 'NSUInteger', interessant .. –

+0

@AlberRenshaw: Es hat wirklich nichts mit' MAX' zu tun. Das Problem ist die Subtraktion. Wenn Sie vorzeichenlose Werte subtrahieren und keinen Unterlauf wünschen, müssen Sie Ihre Werte vor dem Subtrahieren überprüfen. –

+0

Nicht unbedingt, wenn ich den Wert vor der Anwendung von MAX überprüfe, behebt sich das Problem selbst. Wenn ich MAX (b, c) als Integer "d" definiere und dann MAX (a, d), gibt es a zurück. Es scheint also ein Problem mit der Logik hinter der Verarbeitung von MAX zu sein, wenn NSUinteger involviert ist. Verarbeiten Sie den NSUinteger vor der Hand und setzen Sie ihn maximal ein (oder prüfen Sie den Wert vor der Hand und setzen Sie ihn dann auf Maximum), um das Problem zu vermeiden. Hmm –