Преобразование аргументов vararg float
в double
не является причудой или дополнением gcc. Это требуется стандартом C. §6.5.2.3 (вызовы функций):
Если выражение, обозначающее вызываемую функцию, имеет тип, который не включает в себя прототип, целочисленные преобразования выполняются для каждого аргумента, а аргументы, имеющие тип float
, переводятся в double
. Они называются поощрениями аргументов по умолчанию . … Если выражение, которое обозначает вызываемую функцию, имеет тип, который включает в себя прототип, аргументы неявно преобразуются, как если бы путем присваивания, в типы соответствующих параметров, принимая тип каждого параметра вбыть безоговорочной версией объявленного типа. Многоточие в объявлении прототипа функции приводит к тому, что преобразование типа аргумента останавливается после последнего объявленного параметра. Повышение аргументов по умолчанию выполняется на конечных аргументах.
Gcc предоставляет несколько опций, которые не совместимы со стандартом C, но подавляющее большинство добавляет только поведениев случаях, когда стандарт не делает этого. Изменение этой величины будет влиять на стандартное соглашение о вызовах, делая скомпилированный код несовместимым с другим скомпилированным кодом, таким как библиотеки, стандарт или другие. Gcc не предоставляет такой опции. Другие компиляторы могут, но я не знаю ни одного, который это делает.
Обратите внимание, что в рамках ограничений стандарта невозможно просто сделать double
синонимом для float
, если float
является 32-битным значениемМинимальные требования к точности в §5.2.4.2.2 фактически требуют, чтобы у двойника была как минимум 32-битная мантисса в дополнение к показателю степени и знаку. Это намного меньше точности, чем обеспечивается 64-битными двойными кодами IEEE-749, но, очевидно, это больше, чем может быть обеспечено в 32-битном значении.
Компилятор, безусловно, мог бы предоставить опцию, в которой double
s представлены в менее точном и вычислительно более быстром формате, например, два float
s, где мантиссы не перекрываются. (То есть показатели отличаются, по крайней мере, на ширину мантиссы.) Это представление или что-то подобное использовалось, по крайней мере, в одной унаследованной реализации IIRC, именно потому, что оно позволяет использовать оборудование с одинарной точностью для вычислений с двойной точностью,Это также делает приведение float
к double
тривиальным;нужно только сделать младшее значение 0.0. В качестве альтернативы, компилятор может использовать 32-битную мантиссу в сочетании с показателем short
, что позволяет использовать целочисленное значение ALU.
Я не верю, что GCC также предлагает такую альтернативу.