Dlaczego stwierdzenie „2i”; NIE powoduje błędu kompilatora?

82

Zamiast tego 2*iniedbale napisałem 2i:

Spodziewałem się, że kompilator wykryje błąd. Ale tak się nie stało. Czy więc 2iprawidłowe stwierdzenie w C? Jeśli tak, co to robi? Zdziwiony!

Skompilowałem używając gcc w wersji 5.3.0 i oto wynik asemblera:

daltonfury42
źródło
Co to za kompilator?
Iharob Al Asimi
Nie pracuję z _Complexliczbami. Po przeczytaniu standardu i podanego linku myślę, że odpowiedź @ iharob jest poprawna.
zbyt szczery dla tej strony
@Olaf Szybka transformata Fouriera na Zachodzie fftw używa tego _Complextypu. Dowiedziałem się o tym pisząc oprogramowanie do przetwarzania danych na potrzeby mojej pracy magisterskiej ( właściwie fizyka, a nie informatyka lub tym podobne ) - ( musiałem zastosować filtr dolnoprzepustowy, czyli splot, czyli Szybka transformata Fouriera, więc fftw ).
Iharob Al Asimi
@iharob: Hmm, czy to szybsze niż ffte, a jeśli nie, czy mogę używać tego szybciej, jeśli mieszkam na zachodzie, ale na wschód od ciebie? ;-) Poważnie: dzięki za informację. Wygląda na to, że standard C nie obsługuje nawet podobnej prostej notacji z C11.
zbyt szczery dla tej strony
Bardzo dobry przykład „… nie„ Eureka ”, ale„ To zabawne… ”!
Jongware

Odpowiedzi:

107

To jest rozszerzenie gcc i 2ijest wyimaginowaną stałą wprowadź opis obrazu tutaj. Możesz więc napisać liczbę zespoloną w następujący sposób:

Iharob Al Asimi
źródło
12
Wow, to była niespodzianka! Powiesz mi, dlaczego zadziałało, nawet jeśli nie załączyłem pliku nagłówkowego complex.h?
daltonfury42
4
@ daltonfury42 Nagłówek jest dla _Complextypu, 2ijest stałą ( w rozumieniu gcc ). Dodaj flagę std=c99lub std=c11połączoną z, -Walla zobaczysz ostrzeżenie. Co więcej, rzeczywiście nie zwraca, 0ale ponieważ typ zwracania powinien być _Complexi wartość 0 + 2i, nie możesz tego sprawdzić printf(). Więc może to tylko prawdziwa część 0!
Iharob Al Asimi
12
@ daltonfury42: Nie musisz #include <float.h>(lub math.h), aby uzyskać obsługę stałych zmiennoprzecinkowych .
zbyt szczery dla tej strony
2
@ daltonfury42 Zgadza się. Pliki nagłówkowe nie zmieniają składni języka, po prostu deklarują takie rzeczy, jak zmienne, funkcje, typy itp.
Barmar
2
@ daltonfury42 Chociaż możliwe było by rozpoznawanie tej składni było kontrolowane przez a #pragma, co complex.hmogłoby spowodować błąd. Ale nie zrobili tego w ten sposób.
Barmar
13

2ijest gccrozszerzeniem zespolonego literału liczby całkowitej, czystej liczby urojonej, która jest dwa razy większa od pierwiastka kwadratowego -1. To rozszerzenie jest również obsługiwane przez clang.

Zaskakujące jest to, że kompilacja z gcc 5.4.0generuje wysłany wynik montażu:

  • Kompilując na http://gcc.godbolt.org/# Otrzymuję błąd kompilacji z gcc5.3.0 http://gcc.godbolt.org/#:: error: cannot convert '__complex__ int' to 'int' in return.
  • Wysłany kod asemblera funkcji foojest nieprawidłowy: nie zwraca 0. Przekształcenie stałej zespolonej liczby całkowitej 2ina intpowinno zwrócić jej część rzeczywistą 0.

I odwrotnie, w wersji clang3.7 kompiluje się bez ostrzeżenia i generuje optymalny kod, ale oczywiście nie taki, jakiego oczekujesz:

Tę składnię można łączyć z innymi przyrostkami w dowolnej kolejności. Kompilacja poniższego kodu clang -Weverythingdaje mi odpowiednie ostrzeżenia warning: imaginary constants are a GNU extension [-Wgnu-imaginary-constant]:

Tworzy ten wynik w moim środowisku:

Wypróbuj ostatnią za pomocą edytora kolorowania składni ;-)

chqrlie
źródło
Cóż, to właśnie otrzymałem, kiedy użyłem GCC 5.3.0 na moim komputerze z Arch Linux. Oto moja konfiguracja gcc, jeśli jesteś zainteresowany.
daltonfury42