__FLT_MAX__ и __DBL_MAX__ в 0?

В GCC 9.1 при вызове функций std::numeric_limits с типами с плавающей точкой в ​​большинстве случаев они возвращают 0.

Это происходит в проекте, над которым я работаю, и нет проблем с MSVC, GCC 8.3 или Clang 8.0. <double>::epsilon() иногда имеет правильное значение, но при вызове из других файлов оно может также принимать значение 0.

// Commented values at the end of the lines are the values given by the debugger
// Making the variable constexpr doesn't change their values

auto intMax = std::numeric_limits<int>::max(); // {int} 2147483647

auto floatMax     = std::numeric_limits<float>::max();     // {float} 0
auto floatEpsilon = std::numeric_limits<float>::epsilon(); // {float} 0
auto floatMin     = std::numeric_limits<float>::min();     // {float} 0
auto floatLowest  = std::numeric_limits<float>::lowest();  // {float} -0

auto doubleMax     = std::numeric_limits<double>::max();     // {double} 0
auto doubleEpsilon = std::numeric_limits<double>::epsilon(); // {double} 2.2204460492503131e-16
auto doubleMin     = std::numeric_limits<double>::min();     // {double} 0
auto doubleLowest  = std::numeric_limits<double>::lowest();  // {double} -0

std::cout << std::setprecision(10) << std::fixed
          << "Max int        = " << std::numeric_limits<int>::max()
          << "\n"
          << "\nMax float      = " << std::numeric_limits<float>::max()
          << "\nEpsilon float  = " << std::numeric_limits<float>::epsilon()
          << "\nMin float      = " << std::numeric_limits<float>::min()
          << "\nLowest float   = " << std::numeric_limits<float>::lowest()
          << "\n"
          << "\nMax double     = " << std::numeric_limits<double>::max()
          << "\nEpsilon double = " << std::numeric_limits<double>::epsilon()
          << "\nMin double     = " << std::numeric_limits<double>::min()
          << "\nLowest double  = " << std::numeric_limits<double>::lowest() << std::endl;

(The <int>::max() здесь оставлена ​​как ссылка)

Результат в независимом файле (правильные значения):

Max int        = 2147483647

Max float      = 3.40282e+38
Epsilon float  = 1.19209e-07
Min float      = 1.17549e-38
Lowest float   = -3.40282e+38

Max double     = 1.79769e+308
Epsilon double = 2.22045e-16
Min double     = 2.22507e-308
Lowest double  = -1.79769e+308

Результат в проекте:

Max int        = 2147483647

Max float      = 0
Epsilon float  = 0
Min float      = 0
Lowest float   = -0

Max double     = 0
Epsilon double = 2.22045e-16
Min double     = 0
Lowest double  = -0

При независимой компиляции выделенного файла значения верны: тогда проблема не в GCC (как я и ожидал), а скорее всего в конфигурации проекта.

РЕДАКТИРОВАТЬ: компиляция файла проекта (в котором эта проблема возникает в данный момент) также дает правильные результаты. С участием gcc -dM -E, __DBL_MAX__ определяется для double(1.79769313486231570814527423731704357e+308L),

__DBL_MAX__ значение определено, код, окруженный ifdef, выполняется:

#ifdef __DBL_MAX__
#pragma message "__DBL_MAX__ defined"
#endif

/*
note: #pragma message: __DBL_MAX__ defined
   40 | #pragma message "__DBL_MAX__ defined"
      |                 ^~~~~~~~~~~~~~~~~~~~~
*/

GDB дает точно такое же значение, поэтому нет проблем с выходной частью. Выведение XXX_YYY или же __XXX_YYY__ дает те же результаты, так как функции numeric_limits вызывают их в любом случае.

Чтобы быть на 100% ясным: std::numeric_limits<double>::max() == 0 возвращает true, поэтому в выходной части проблем нет. Это просто оставлено здесь в качестве ссылки.

В чем может быть причина (ы) GCC производит такое поведение? не являются __XXX_YYY__ встроенные значения в любом случае? Как они могут держать 0?

1 ответ

Решение

Таким образом, ошибка произошла (по крайней мере косвенно) из предварительно скомпилированных заголовков, которые мы используем вместе с cotire для CMake.

Каждый файл, включенный этими заголовками, вручную включенный в "проблемные" файлы, не воспроизводил проблему.

Хотя это и немного странно, но пока я не вижу никаких других приемлемых объяснений, кроме как поступить в общежитии. По-видимому, уже сообщалось о проблемах с ограничениями в соответствии с этой веткой: сборка C++ Cmake с cotire и gtest - error с float.h

Тогда временным решением будет отключение предварительно скомпилированных заголовков с помощью GCC 9.1+. Если у кого-то была такая же проблема, не стесняйтесь добавлять комментарии или ответы, если вы знаете, почему и как это происходит.

Спасибо Джованни, Камилю и Нм в комментариях, которые привели меня в правильном направлении!

Другие вопросы по тегам