Инициализировать переменную статически (во время компиляции)

1) У меня много констант в моем алгоритме. 2) мой код работает как с плавающей, так и с фиксированной точкой.

Прямо сейчас эти константы инициализируются функцией float2fixed, в результате чего в плавающей точке она ничего не делает, а в фиксированной точке находит свое представление с фиксированной точкой. Например, 0.5f остается равным 0.5f, если работает с плавающей запятой, тогда как он использует подпрограмму pow() и становится 32768, если работает с фиксированной запятой, а представление с фиксированной запятой - Qx.16.

Это легко поддерживать, но на самом деле требуется много времени для вычисления этих констант с фиксированной запятой (pow - это функция с плавающей запятой). В C++ я бы использовал некоторое метапрограммирование, поэтому компилятор вычисляет эти значения во время компиляции, так что нет никакого попадания во время выполнения. Но в Си это невозможно. Либо это? Кто-нибудь знает такой трюк? Любой компилятор достаточно умен, чтобы сделать это?

Ждем любых ответов.

4 ответа

Вместо того, чтобы использовать (unsigned)(x*pow(2,16)) чтобы сделать ваше преобразование с фиксированной запятой, запишите его как (unsigned)(0.5f * (1 << 16))

Это должно быть приемлемым в качестве константного выражения во время компиляции, поскольку оно включает только встроенные операторы.

При использовании фиксированной точки вы можете написать программу, которая берет ваши значения с плавающей запятой и преобразует их в правильные, постоянные инициализаторы для типа с фиксированной запятой, так что вы эффективно добавляете шаг к компиляции, который генерирует значения с фиксированной запятой.

Одним из преимуществ этого будет то, что вы можете определить и объявить свои константы с помощью const так что они не изменятся во время выполнения - тогда как с функциями инициализации, конечно, значения должны быть модифицируемыми, потому что они вычисляются один раз.


Я имею в виду написать простую программу, которая может сканировать формульные строки, которые могут выглядеть так:

const double somename = 3.14159;

это прочитало бы это и произвело бы:

const fixedpoint_t somename = { ...whatever is needed... };

Вы разрабатываете операцию, чтобы облегчить управление обеими нотациями, поэтому, возможно, ваш конвертер всегда читает файл, а иногда переписывает его.

datafile.c:   datafile.constants converter
        converter datafile.constants > datafile.c

В последних версиях GCC (около 4.3) добавлена ​​возможность использовать GMP и MPFR для выполнения некоторых оптимизаций во время компиляции путем оценки более сложных постоянных функций. Такой подход делает ваш код простым и переносимым и доверяет компилятору выполнять тяжелую работу.

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

В простом С вы мало что можете сделать. В какой-то момент вам нужно выполнить преобразование, и компилятор не дает вам никакого доступа к вызову интересных пользовательских функций во время компиляции. Теоретически, вы можете попытаться уговорить препроцессор сделать это за вас, но это быстрый путь к полному безумию (то есть вам придется реализовать pow() в макросах, что довольно отвратительно).

Некоторые варианты, которые я могу придумать:

  1. Поддерживать постоянный кеш на диске. По крайней мере, тогда он будет медленным только один раз, хотя вам все равно придется загрузить его, убедиться, что он не поврежден и т. Д.

  2. Как уже упоминалось в другом комментарии, в любом случае используйте шаблонное метапрограммирование и компилируйте его с помощью компилятора C++. Большинство C прекрасно работает (возможно, лучше) с компилятором C++.

Хм, наверное, это все, о чем я могу думать. Удачи.

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