Co to jest operator > = w C?
Podane przez kolegę jako zagadka, nie mogę zrozumieć, jak ten program C faktycznie kompiluje i działa. Co to jest operator >>>=
i dziwny 1P1
dosłowny? Testowałem w Clang i GCC. Nie ma żadnych ostrzeżeń, a wyjście to"???"
#include <stdio.h>
int main()
{
int a[2]={ 10, 1 };
while( a[ 0xFULL?'\0':-1:>>>=a<:!!0X.1P1 ] )
printf("?");
return 0;
}
3 answers
Linia:
while( a[ 0xFULL?'\0':-1:>>>=a<:!!0X.1P1 ] )
Zawiera digrafy :>
i <:
, które tłumaczą się odpowiednio na ]
i [
, więc jest równoważne:
while( a[ 0xFULL?'\0':-1 ] >>= a[ !!0X.1P1 ] )
Literał 0xFULL
jest taki sam jak 0xF
(co jest szesnastkowe dla 15
); ULL
określa tylko, że jest tounsigned long long
literał . W każdym razie, jako boolean jest to prawda, więc 0xFULL ? '\0' : -1
ewaluuje do '\0'
, który jest literałem znaków, którego wartość liczbowa jest po prostu 0
.
Tymczasem 0X.1P1
jest a szesnastkowy literał zmiennoprzecinkowy równy 2/16 = 0,125. W każdym razie, jako niezerowe, jest również prawdziwe jako boolean, więc negowanie go dwa razy z !!
ponownie daje 1
. W ten sposób całość upraszcza się do:
while( a[0] >>= a[1] )
Operator >>=
jest przypisaniem złożonym , który przesuwa swój lewy operand w prawo o liczbę bitów podanych przez prawy operand i zwraca wynik. W tym przypadku właściwy operand a[1]
zawsze ma wartość 1
, więc jest odpowiednik:
while( a[0] >>= 1 )
Lub równoważnie:
while( a[0] /= 2 )
Wartość początkowa a[0]
wynosi 10. Po przesunięciu w prawo raz, staje się 5, następnie (zaokrąglenie w dół) 2, następnie 1 i wreszcie 0, w którym momencie kończy się pętla. W ten sposób ciało pętli jest wykonywane trzy razy.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:54:34
Jest to jakiś dość niejasny kod dotyczący digraphs, mianowicie <:
i :>
, które są alternatywnymi tokenami odpowiednio dla [
i ]
. Istnieje również pewne wykorzystanie operator warunkowy. Istnieje również Operator zmiany bitów, właściwe przypisanie zmiany >>=
.
To jest bardziej czytelna Wersja:
while( a[ 0xFULL ? '\0' : -1 ] >>= a[ !!0X.1P1 ] )
I jeszcze bardziej czytelną wersję, zastępując wyrażenia w []
wartościami rozstrzygnęli na:
while( a[0] >>= a[1] )
Zastąpienie a[0]
i a[1]
ich wartości powinno ułatwić ustalenie, co robi pętla, tj. odpowiednik:
int i = 10;
while( i >>= 1)
, który po prostu wykonuje (integer) dzielenie przez 2 w każdej iteracji, tworząc sekwencję 5, 2, 1
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-26 18:56:31
Przejdźmy do wyrażenia od lewej do prawej:
a[ 0xFULL?'\0':-1:>>>=a<:!!0X.1P1 ]
Pierwszą rzeczą, jaką zauważyłem, jest to, że używamy operatora trójdzielnego z użycia ?
. Więc podwyrażenie:
0xFULL ? '\0' : -1
Mówi " Jeśli 0xFULL
jest niezerowe, zwróć '\0'
, w przeciwnym razie -1
. 0xFULL
jest szesnastkowym literałem zunsigned long-long sufiksem - co oznacza, że jest szesnastkowym literałem typu unsigned long long
. To jednak nie ma znaczenia, ponieważ 0xF
może zmieścić się wewnątrz zwykłego liczba całkowita.
Ponadto operator trójdzielny przekształca typy drugiego i trzeciego terminu na ich wspólny typ. {[9] } jest następnie konwertowane do int
, co jest po prostu 0
.
Wartość 0xF
jest znacznie większa od zera, więc przechodzi. Wyrażenie staje się teraz:
a[ 0 :>>>=a<:!!0X.1P1 ]
Następny, :>
jest } digraf . Jest to konstrukcja, która rozszerza się do ]
:
a[0 ]>>=a<:!!0X.1P1 ]
>>=
jest podpisanym prawym operatorem przesunięcia, możemy go spacji z a
, aby jaśniej.
Ponadto, <:
jest digrafem, który rozszerza się do [
:
a[0] >>= a[!!0X.1P1 ]
0X.1P1
jest literałem szesnastkowym z wykładnikiem. Ale bez względu na wartość, !!
wszystkiego, co jest niezerowe, jest prawdziwe. 0X.1P1
jest 0.125
które jest niezerowe, więc staje się:
a[0] >>= a[true]
-> a[0] >>= a[1]
>>=
jest podpisanym prawym operatorem zmiany. Zmienia wartość swojego lewego operandu, przesuwając jego bity do przodu o wartość po prawej stronie operatora. 10
w binarnym jest 1010
. Więc oto kroki:
01010 >> 1 == 00101
00101 >> 1 == 00010
00010 >> 1 == 00001
00001 >> 1 == 00000
>>=
zwraca wynik swojej operacji, tak długo jak przesunięcie a[0]
pozostanie niezerowe za każdym razem, gdy jego bity zostaną przesunięte w prawo o jeden, pętla będzie kontynuowana. Czwarta próba to miejsce, w którym a[0]
staje się 0
, więc pętla nigdy nie jest wprowadzana.
W rezultacie ?
jest drukowany trzy razy.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-30 02:41:41