С++ объявляет платформу независимым 32-битным поплавком
Есть ли способ объявить 32-битное значение с плавающей запятой в С++, гарантируя, что он всегда будет 32 бита независимо от платформы/компилятора?
Я могу сделать это для целых чисел:
#include <stdint.h>
uint32_t var; //32 bit unsigned integer
uint64_t var1; //64 bit unsigned integer
Есть ли способ сделать что-то подобное для поплавков? Насколько я знаю,
float var; //Usually is 32 bit, but NOT GUARANTEED to be 32 bit
является специфичной для реализации, и не обязательно 32 бит. (Исправьте меня, если я ошибаюсь).
Я использую qt, поэтому, если есть какое-либо решение, использующее его, я бы принял его - я не мог найти ничего подобного quint16 для float (qreal изменяет размер в зависимости от платформы).
Ответы
Ответ 1
Вы используете Qt. который специфичен для С++, поэтому я не уверен, почему вопрос помечен C.
Насколько мне известно, на всех платформах, где поддерживается Qt, введите float
32-разрядный IEEE.
Если кто-то решит перенести Qt на, скажем, векторный механизм Cray с 64-битным float
, вы все равно не будете иметь 32-битный тип с плавающей точкой (если вы не реализуете его самостоятельно в программном обеспечении, но я не вижу, как это было бы полезно).
Нет <stdfloat.h>
/<cstdfloat>
, соответствующего <stdint.h>
/<cstdint>
. C и С++ предоставляют float
, double
и long double
и накладывают на них минимальные требования, но не дают вам способа спросить тип с плавающей точкой любого определенного размера.
Лучше всего добавить что-то вроде этого в main
или в какую-то функцию, которая должна быть вызвана во время запуска программы:
assert(CHAR_BIT * sizeof (float) == 32);
и, возможно, CHAR_BIT == 8
, если ваш код неявно зависит от этого.
Маловероятно, что assert
будет когда-либо срабатывать - и если это произойдет, у вас будут большие проблемы.
Возможно, вам захочется пересмотреть, нужен ли вам 32-разрядный плавающий тип. Если ваш код работал в системе с 64-битным float
, как это не соответствовало бы вашим требованиям?
Ответ 2
Существует не такой размер с плавающей запятой, но вы всегда можете статически утверждать, что размер 32 бит. Может быть, даже что-то столь же простое, как глобальный массив char:
#include <climits>
char static_assert_float32[1 - (2 * ((sizeof(float) * CHAR_BIT) != 32))];
Это не скомпилируется, если float
не 32 бит, объявив массив отрицательного размера.
Ответ 3
Наиболее распространенные реализации C и С++ будут использовать 32-битные типы float
. Если вам действительно нужно поймать любые платформы, где этого не произойдет, вы можете использовать следующее, чтобы пропустить ошибку в начале программы:
#include <limits.h>
if (sizeof(float) * CHAR_BIT != 32)
// error code here
К сожалению, я не знаю способа обнаружить его во время компиляции, мой ранний ответ был ошибочным.
Ответ 4
На платформе, поддерживающей IEEE-754 float
, она будет 32 бит. На платформах, которые этого не делают, разная ширина, вероятно, будет наименьшей из ваших проблем. Нижняя строка - используйте float
и не волнуйтесь.
Ответ 5
Знание того, что sizeof (float) равно 32 битам, может быть достаточно, в общем, но недостаточно во всех случаях.
IEEE 758 определяет хорошо известный 32-битный двоичный файл32, который обычно реализуется. Но IEEE 758 также определяет 32-разрядный decimal32, который в основном используется для хранения, а не для вычисления. Существуют также другие 32-разрядные версии с плавающей запятой, отличные от IEEE 758, но, конечно, не такие общие.
Даже если известно, что float
- это 32-разрядный IEEE 758-2008 binary32, степень, в которой данная среда придерживается своих строгих определений (Nan, subnormals, rounding modes), может различаться. Я подозреваю, что это самый большой источник тонких вариаций 32-float-реализаций.
Таким образом, цель знать точно используемую модель с плавающей запятой, которая, вероятно, обеспечит согласованность между платформами, может быть очень сложной для обнаружения во время компиляции.