2017-02-08 56 views
7

Tak, napisałem jakiś kod i otrzymałem nieoczekiwane dane wyjściowe w jednej części mojego programu, które zakłóciły cały system.Wyrażenia logiczne w nieporozumieniu C

Udało mi się wydobyć i uprościć problem do podstawowego wyrażenia logicznego. Powiedzmy:

int i = 1, j = 1, k = 0; 

printf("%d\n", ++i || ++j && k); 
printf("%d, %d, %d\n", i, j, k); 

return 0; 

Wyjście dla tego programu jest:

1

210

myślę, że wartość j nie był zwiększany do 2 ze względu na krótki charakter obwodu operatora ||. Jednak jestem zdezorientowany, jak wartość pierwszego "%d" jest 1. Czy wartość k nie powinna być równa zero dla oświadczenia &&, aby zwrócić 1? Czy też to polecenie nie jest w ogóle wykonywane, ponieważ ++i || ++j nie jest 0 i dlatego zwraca wartość 1?

  • wiem, że && jest logicznym i i wyr1 & & wyr2 ma wartość 1, jeśli wartości wyr1 & & wyr2zarówno niezerową.

Zostanie docenione wszelkie wyjaśnienia i proszę wybaczyć podstawową naturę tego pytania.

Odpowiedz

7

&& ma wyższy priorytet niż ||. (patrz https://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B) tak

++i || ++j && k 

jest

++i || (++j && k) 

i || shortcircuits jeżeli pierwszy operator truthy, zgodnie 6.5.14p4.

Jeśli jesteś na gcc lub clang i skompilujesz swój kod z -Wall, kompilator popchnie Cię, aby umieścić tam nawiasy. To chyba dobry pomysł, aby posłuchać tej rady, ponieważ niektórzy ludzie są zdezorientowani przez pierwszeństwo (słyszę).

+0

Niestety używam VS2015. Wkrótce będę chciał zacząć używać 'gcc'. Zakładam, że sugerowałbyś to zrobić? Zawsze używałem VS, ponieważ jest zalecane dla studentów ... (tak mi się wydawało) –

+2

@Rizzo Myślę, że gcc jest zdecydowanie świetnym kompilatorem, zarówno pod względem wygody programistów, jak i szybkości generowanego kodu, ale używaj tego, co lubisz. ;) – PSkocik

2

++i || ++j && k jest oceniany jako 1 (prawda), ponieważ jest równy 2 (++ 1), (++ j & & k) nie jest oceniany, ponieważ występuje zwarcie.

3

od C Standard (6.5.14 operatora logicznego OR)

3 || operator podaje 1, jeśli którykolwiek z jego argumentów operacji porównuje nierównomierny do 0; w przeciwnym razie daje 0. Wynik ma typ int.

Wyrażenie

++i || ++j && k 

odpowiada

++i || (++j && k) 

i według kursu od normy ekspresję powraca liczbę całkowitą 1, ponieważ ++i nie jest równa zeru. Podwyrażenia (++j && k) nie są oceniane.

1

Priorytety operatorów. && ma wyższy priorytet niż ||.

wyrażenia jest taki sam jak: ++i || (++j && k)

++i jest TRUE, nawias nie jest analizowany już.