Zamiast tego 2*i
niedbale napisałem 2i
:
int foo(int i)
{
2i;
return 2i;
}
Spodziewałem się, że kompilator wykryje błąd. Ale tak się nie stało. Czy więc 2i
prawidł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:
.file "strange.c"
.text
.globl foo
.type foo, @function
foo:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl %edi, -4(%rbp)
nop
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size foo, .-foo
.ident "GCC: (GNU) 5.3.0"
.section .note.GNU-stack,"",@progbits
_Complex
liczbami. Po przeczytaniu standardu i podanego linku myślę, że odpowiedź @ iharob jest poprawna._Complex
typu. 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 ).Odpowiedzi:
To jest rozszerzenie gcc i
2i
jest wyimaginowaną stałą . Możesz więc napisać liczbę zespoloną w następujący sposób:#include <complex.h> _Complex x = 4 + 5i;
źródło
_Complex
typu,2i
jest stałą ( w rozumieniu gcc ). Dodaj flagęstd=c99
lubstd=c11
połączoną z,-Wall
a zobaczysz ostrzeżenie. Co więcej, rzeczywiście nie zwraca,0
ale ponieważ typ zwracania powinien być_Complex
i wartość0 + 2i
, nie możesz tego sprawdzićprintf()
. Więc może to tylko prawdziwa część0
!#include <float.h>
(lubmath.h
), aby uzyskać obsługę stałych zmiennoprzecinkowych .#pragma
, cocomplex.h
mogłoby spowodować błąd. Ale nie zrobili tego w ten sposób.2i
jestgcc
rozszerzeniem 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 przezclang
.Zaskakujące jest to, że kompilacja z
gcc 5.4.0
generuje wysłany wynik montażu:gcc
5.3.0http://gcc.godbolt.org/#
::error: cannot convert '__complex__ int' to 'int' in return
.foo
jest nieprawidłowy: nie zwraca0
. Przekształcenie stałej zespolonej liczby całkowitej2i
naint
powinno zwrócić jej część rzeczywistą0
.I odwrotnie, w wersji
clang
3.7 kompiluje się bez ostrzeżenia i generuje optymalny kod, ale oczywiście nie taki, jakiego oczekujesz:foo(int): # @foo(int) xorl %eax, %eax retq
Tę składnię można łączyć z innymi przyrostkami w dowolnej kolejności. Kompilacja poniższego kodu
clang -Weverything
daje mi odpowiednie ostrzeżeniawarning: imaginary constants are a GNU extension [-Wgnu-imaginary-constant]
:#include <stdio.h> int main() { /* complex integer literals */ printf("sizeof(2i) = %zd\n", sizeof(2i)); printf("sizeof(2ui) = %zd\n", sizeof(2ui)); printf("sizeof(2li) = %zd\n", sizeof(2li)); printf("sizeof(2lli) = %zd\n", sizeof(2lli)); /* complex floating point literals */ printf("sizeof(2.i) = %zd\n", sizeof(2.i)); printf("sizeof(2.fi) = %zd\n", sizeof(2.fi)); printf("sizeof(2e0fi) = %zd\n", sizeof(2e0fi)); printf("sizeof(2e0i) = %zd\n", sizeof(2e0i)); /* alternate order */ printf("sizeof(2il) = %zd\n", sizeof(2il)); printf("sizeof(2ill) = %zd\n", sizeof(2ill)); printf("sizeof(2.if) = %zd\n", sizeof(2.if)); return 0; }
Tworzy ten wynik w moim środowisku:
sizeof(2i) = 8 sizeof(2ui) = 8 sizeof(2li) = 16 sizeof(2lli) = 16 sizeof(2.i) = 16 sizeof(2.fi) = 8 sizeof(2e0fi) = 8 sizeof(2e0i) = 16 sizeof(2il) = 16 sizeof(2ill) = 16 sizeof(2.if) = 8
Wypróbuj ostatnią za pomocą edytora kolorowania składni
;-)
źródło