Создание массива размер которого вычисляется на этапе компиляции (expression must have a constant value)

Рейтинг: 2Ответов: 2Опубликовано: 07.04.2023

Почему компилятор ругается на такой код:

...
const double X_MIN = 2.0;
const double X_MAX = 3.0;
const double H = .1;
...
const int n = static_cast<int>((X_MAX - X_MIN)/H) + 1;
double arrResQuanc[n] = { 0 };

Err: expression must have a constant value

Например этот код компилируется без проблем

const int K_MIN = 1;
const int K_MAX = 10;
const int nK = K_MAX - K_MIN + 1;
double arrXk[nK] = { 0 };

Ответы

▲ 0

А вы попробуйте проще:

const int i = 1.22;
constexpr int n = i;

правильно, потому что правое выражение содержит целое, которое является константным выражением 1, а для чисел с плавающей точкой не так, потому что для них проводится экспоненциальная запись(читайте как хранятся double). Вы можете написать:

const double d = 1.22 /3;

Кажется что результат должен быть константным выражением, поскольку делятся два литерала. Но это не так:

constexpr double e = d; 

уже является ошибкой, потому что d может иметь бесконечно или очень много знаков после плавающей точки, и в зависимости от показателья степени(экспоненты), может быть представлен по разному, и в итоге будет округлен, дабы вмещаться в выделенные для типа байты. Если взять 10 знаков, то это число: 40666.66667 / 10^5 или же вам может быть нужно округление до 6 знаков? Тогда это число 0.40667 и так далее. Теперь эти два числа умножте на 10^5 и получите совершенно разные целые. Надеюсь я смог объяснить почему одним словом константное целое воспринимается также как константное выражение, а константное число с плавающей точкой не считается и константным выражением. Об этом компилятору явно нужно сказать, указав явно, что это не константа а именно constexpr

▲ -1

Всё дело в том, что const к переменной это приставка для оптимизации компилятора и надёжности к программированию. Программист может отправлять ссылку на переменную, которая постоянно меняется и её может передавать как константу.
Размеры массива должны быть заданы не простой переменной, а той, чьё значение уже вычислено на этапе компиляции. И обозначение constexpr именно это и делает.

constexpr double X_MIN = 2.0;
constexpr double X_MAX = 3.0;
constexpr double H = .1;
constexpr int n = static_cast<int>((X_MAX - X_MIN)/H) + 1;
double arrResQuanc[n] = { 0 };