2016-02-28 7 views
8

Ein Freund von mir hat mir scherzhaft diese Frage gestellt. Es sollte eine Bemerkung vom Typ "geht ohne zu sagen" sein, aber dann habe ich eine Weile darüber nachgedacht und mit einigen cleveren "fast Lösungen" angefangen.Wann ist (x ||! X) falsch?

Erster Versuch:

Wenn C unterstützt jemals Quantencomputing kann es eine Antwort darauf sein. Ein q-Bit kann in vielen Zuständen gleichzeitig sein, also könnte es false AND true sein und diese Bedingung gibt (BOOL)0.5 alias "Ja/nein/vielleicht-so" zurück - aber sobald Sie die Variable beobachten, wird die ganze Sache zusammenbrechen und ungültig werden nochmal.

Zweiter Versuch:

Wenn X irgendwie als zufälliger binärer Generator definiert werden könnte und man wirft ihn auf ein BOOL Sie einen Teil der Zeit falsch bekommen können. Ich bin mir nicht sicher, ob Sie dies tun können, aber in C, wenn Sie CLANG verwenden. #define x (BOOL)!!(rand()%2)



Die Sprache, die wir diese in der Diskussion wurden ist C aber ich bin auch gespannt, ob jemand irgendwelche Lösungen in jede Sprache finden können.

+2

Antwort: Undefiniertes Verhalten. – SLaks

+9

Das ist die Frage, die Hamlet vor hunderten von Jahren stellte: 'bb || ! bb'. – nsilent22

+0

@ nsilent22 Ich lachte etwas hardhard –

Antwort

16

Wenn x flüchtig ist (volatile int x) und wird von einem Außengewinde/Gerät modifiziert, kann der Ausdruck falsch sein.

+0

Interessante Lösung! Ich frage mich, ob es einen Weg gibt, dies zu tun, ohne die Variable direkt an einem anderen Punkt im Code zu ändern. –

+0

Wie ich bereits sagte, wenn 'x' auf einen extern modifizierten Speicherort/Register gemappt wird, kann es" spontan "passieren. – Amit

+0

Oh Du hast recht! Das ist ziemlich genial! Obwohl es nicht immer falsch ist, hmm –

4

Makros betrügen hier wirklich, aber Sie brauchen nichts mit booleschen Typen oder speziellen Compilern zu tun. Im Folgenden, soweit ich weiß, ist rechtlich C.

#include <stdio.h> 
int f(void) { 
    static int y = 0; 
    if (y == 0) { 
    y = 1; 
    return 0; 
    } else { 
    return 1; 
    } 
} 

#define x f() 

int main(void) { 
    if (x || !x) { 
    puts("It was true"); 
    } else { 
    puts("It was false"); 
    } 
    return 0; 
} 

Oder noch prägnanter:

int y = 0; 
#define x y++ 

(Für diejenigen besorgt über undefiniertes Verhalten, beachten Sie, dass ein Sequenzpunkt zwischen der linken Seite und die rechte Seite von ||)

+0

Ich arbeitete an etwas wie das mit CLANG in Obj-C. Ich habe so weit '# define x (BOOL) [[NSUserDefaults standardUserDefaults] integerForKey: @" x "]; [[NSUserDefaults standardUserDefaults] setInteger: (int)! (BOOL) [[NSUserDefaults standardUserDefaults] integerForKey: @" x "] forKey: @ "x"]; [[NSUserDefaults standardUserDefaults] synchronisieren]; 'bevor ich realisiere, kann ich keine Funktionen innerhalb von Bedingungen in Ziel-c haben (soweit ich weiß) –

+0

@AlberRenshaw: Ich habe keine Ahnung was das tut es, aber es scheint waaaaaaaaay kompliziert zu sein. –

9

Es ist ein bisschen wie ein Trick, aber die folgende Lösung funktioniert auch.

#define x 1 ? 0 : 1 
(x || !x) 

Der Grund liegt in der Vorrangstellung des Operators. Nach der Vorverarbeitung (x || !x) löst die folgenden (Klammern hinzugefügt, um den Vorrang zu zeigen):

(1 ? 0 : (1 || !1) ? 0 : 1) 
+1

Das ist genial - fav Antwort so weit –

+2

Sie können es noch einfacher machen: '#define x 1 && 0' oder sogar' #define x 1,0' – Joni

+0

@Joni Das ist eine gute Antwort! Bitte poste es: D –

4

Eine noch einfachere Makro:

#define x 0&0 

(x || !x) Erweiterung gibt (0 & 0 || !0 & 0) die immer falsch ist.

Ähnlich:

#define x 0*0 
#define x 1*0 // for binary buffs 
#define x 4&2 // for HHGG fans. 

Ich konnte kein 2-Buchstaben-Makro finden :(

+0

In diesem Fall würde jedes Makro '... & 0' funktionieren – vittore

+1

@vittore: in der Tat würde '1 & 0' funktionieren und hat weniger Pixel, und' 4 & 2' ist nerdyiger. – chqrlie

2

Wenn x eine charecter Typ ist (dh nicht int oder Bool), dann einige Sprache wie JS, PHP usw. können die Folge sein der Ausdruck als falsch.

die

für

im Falle von Typ Gussfehler bedeutet

char x = "string";

(x ||! X) = False (0 oder NaN)

, dass Sprache, die sie gut type casting unterstützen keine Fehler aufwiesen oder dieser Fehler kann durch Selbst Gießen entfernt werden.

selbst gegossen, z.B. char a = "10"; int b = (int) a;

neu ver. der Sprache gehören auch Teig Cast Engeine.

1

in JS Versuchte:

var i = 0

i ++ || ! (i ++)

Hinweis: Diese Lösung funktioniert nur, wenn i = 0

+0

drücken Sie bitte die Codebeispieltaste, die als {} angezeigt werden kann, und fügen Sie dann Ihren Code ein. –