Почему утверждение «2i;» НЕ вызывает ошибку компилятора?

82

Вместо этого 2*iя небрежно написал 2i:

Я ожидал, что компилятор поймает ошибку. Но этого не произошло. Итак, 2iдопустимое утверждение на C? Если да, то что он делает? Озадачен!

Я скомпилировал с помощью gcc версии 5.3.0, и вот результат сборки:

daltonfury42
источник
Что это за компилятор?
Ихароб Аль Асими
Я не работаю с _Complexчислами. После некоторого чтения в стандарте и предоставленной ссылке я думаю, что ответ @iharob правильный.
слишком честно для этого сайта
@Olaf Быстрое преобразование Фурье на Западе fftw использует этот _Complexтип. Я обнаружил это при написании программного обеспечения для обработки данных для моей диссертации (на самом деле физика, а не информатика или что-то подобное ) - ( мне пришлось применить фильтр нижних частот, поэтому свертка, быстрое преобразование Фурье, так что fftw ).
Ихароб Аль-Асими
@iharob: Хм, это быстрее, чем ffte, и если нет, могу ли я использовать более быстрый, если я живу на западе, но к востоку от вас? ;-) Серьезно: спасибо за информацию. Кажется, что стандарт C даже не поддерживает аналогичную простую нотацию с C11.
слишком честно для этого сайта
Очень хороший пример «.. не« Эврика », а« Это смешно ... »»!
Jongware 03

Ответы:

107

Это расширение gcc и 2iмнимая константа введите описание изображения здесь. Итак, вы можете написать сложное число так:

Ихароб аль-Асими
источник
12
Вау, это стало неожиданностью! Вы скажете мне, почему это сработало, даже если я не включил заголовочный файл complex.h?
daltonfury42
4
@ daltonfury42 Заголовок предназначен для _Complexтипа, 2iявляется константой ( в понимании gcc ). Добавьте флаг std=c99или в std=c11сочетании с, -Wallи вы увидите предупреждение. Кроме того, он действительно не возвращается, 0но поскольку тип возврата должен быть _Complexи значением 0 + 2i, вы не можете его проверить printf(). Так что, возможно, это только настоящая часть 0!
Ихароб Аль-Асими
12
@ daltonfury42: Вам также не нужно #include <float.h>(или math.h) получать поддержку констант с плавающей запятой .
слишком честно для этого сайта
2
@ daltonfury42 Верно. Заголовочные файлы не меняют синтаксис языка, они просто объявляют такие вещи, как переменные, функции, типы и т. Д.
Бармар
2
@ daltonfury42 Хотя для распознавания этого синтаксиса можно было управлять с помощью a #pragma, который complex.hможет выдавать. Но они этого не сделали.
Barmar 03
13

2iявляется gccрасширением комплексного целочисленного литерала, чисто мнимого числа, удвоенного квадратного корня из -1. Это расширение также поддерживается clang.

Несколько удивительно, что ваша компиляция с помощью gcc 5.4.0дает опубликованный вывод сборки:

  • При компиляции на http://gcc.godbolt.org/# я получаю ошибку компиляции из gcc5.3.0 http://gcc.godbolt.org/#:: error: cannot convert '__complex__ int' to 'int' in return.
  • Опубликованный код сборки для функции fooневерен: он не возвращается 0. Преобразование комплексной целочисленной константы 2iв intдолжно возвращать ее действительную часть 0.

И наоборот, в clangверсии 3.7 он компилируется без предупреждения и генерирует оптимальный код, но, конечно, не то, что вы ожидаете:

Этот синтаксис можно комбинировать с другими суффиксами в любом порядке. Компиляция кода ниже clang -Weverythingдает мне соответствующие предупреждения warning: imaginary constants are a GNU extension [-Wgnu-imaginary-constant]:

Он производит такой вывод в моей среде:

Попробуйте последний вариант с помощью редактора раскраски синтаксиса ;-)

chqrlie
источник
Что ж, это то, что я получил, когда использовал GCC 5.3.0 на своем ПК с Arch Linux. Вот моя конфигурация gcc, если вам интересно.
daltonfury42