Ответ 1
Это расширение gcc, а 2i
- мнимая константа . Поэтому вы можете написать сложное число, например:
#include <complex.h>
_Complex x = 4 + 5i;
Вместо 2*i
я небрежно написал 2i
:
int foo(int i)
{
2i;
return 2i;
}
Я ожидал, что компилятор поймает ошибку. Но это не так. Итак, 2i
действительный оператор в C? Если да, то что он делает? Озадаченный!
Я скомпилировал с использованием gcc версии 5.3.0, и вот сборка:
.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
Это расширение gcc, а 2i
- мнимая константа . Поэтому вы можете написать сложное число, например:
#include <complex.h>
_Complex x = 4 + 5i;
2i
является расширением gcc
для целочисленного целочисленного литерала, чистого мнимого числа, в два раза превышающего квадратный корень из -1
. Это расширение поддерживается также clang
.
Несколько удивительно, что ваш компиляция с помощью gcc 5.4.0
создает опубликованный вывод сборки:
gcc
5.3.0: http://gcc.godbolt.org/#
: error: cannot convert '__complex__ int' to 'int' in return
.foo
: он не возвращает 0
. Преобразование целочисленной целочисленной константы 2i
в int
должно возвращать ее действительную часть 0
.И наоборот, с clang
3.7, он компилируется без предупреждения и генерирует оптимальный код, но, конечно, не то, что вы ожидаете:
foo(int): # @foo(int)
xorl %eax, %eax
retq
Этот синтаксис можно комбинировать с другими суффиксами в любом порядке. Компиляция кода ниже с помощью clang -Weverything
дает мне соответствующие предупреждения warning: 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;
}
Он производит этот вывод в моей среде:
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
Попробуйте последний с помощью редактора раскраски синтаксиса ;-)