|
|
  |
Вычисление констант, Возможности компилятора. |
|
|
|
Oct 2 2006, 09:32
|
Местный
  
Группа: Участник
Сообщений: 416
Регистрация: 18-04-06
Из: Челябинск
Пользователь №: 16 219

|
Цитата(SasaVitebsk @ Oct 2 2006, 12:11)  Мне необходимо, для универсальности воспользоваться формулой для вычисления константы. В описании языка Си я не нашёл некоторых моментов. Например мне надо операция возведения в степень. То есть чтобы компилятор высчитал и подставил численное выражение. Ну например.
#define NUMBRZR 8 // Число отображаемых разрядов #define DECIMAL 10 // Тип счёта ..... j=powl(DECIMAL,NUMBRZR)-1; // Инициализировать значения .....
Иными словами я хочу получить "99999999" в операторе присваивания. И функция здесь конечно не причём. Это выражение вычисляется на этапе компиляции.
Как написать возведение в степень? Никак. На этапе компиляции происходит только вычисление константных выражений. У компилятора нет каких либо встроенных функций. Поэтому, если Вы хотите вычислять функции при инициализации, то либо Вы это делаете вручную, либо иниализация будет выполнятся во время выполнения программы. В последнем случае компилятор будет генерировать код для вызова соответствующей функции.
|
|
|
|
|
Oct 3 2006, 03:35
|

Adept
     
Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343

|
Цитата(SasaVitebsk @ Oct 2 2006, 22:48)  Цитата(_Bill @ Oct 2 2006, 12:32)  Никак. На этапе компиляции происходит только вычисление константных выражений. У компилятора нет каких либо встроенных функций. Поэтому, если Вы хотите вычислять функции при инициализации, то либо Вы это делаете вручную, либо иниализация будет выполнятся во время выполнения программы. В последнем случае компилятор будет генерировать код для вызова соответствующей функции.
Это приятно. У меня был ассемблер х51. Так вот он это умел делать. Это частные особенности того ассемблера. По Стандарту С/С++ компилятор не обязан рассчитывать такие выражения. Цитата(SasaVitebsk @ Oct 2 2006, 22:48)  А на AVR Studio столкнулся с потерей точности. Надо формулу правильно писать. А то сначала поделит (отбросит лишнее) потом умножит, - ну и привет.  Это Вы, наверное, препроцессор имеете в виду? Он - да, на этапе компиляции рассчитывает. Но только в целых числах и только в 32-х битах. Часто этого оказывается достаточно. Только препроцессор не константы инициализирует, а макросы. А с константами уже работает компилятор. Но это уже не следующем этапе. И вот компилятор ничего вычислять на этапе компиляции не обязан. Максимум он может прооптимизировать инициализатор, если там не используются, например, функции типа синуса или логарифма. Цитата(SasaVitebsk @ Oct 2 2006, 22:48)  Как правило компиляторы PC поступаю правильно. То есть определяют если выражение константное, то сразу подставляют его значение. Компиляторы PC делают это на рантайме (при загрузке программы), как и всякие другие компиляторы С/С++. Просто рантайм у PC намного дешевле, чем у МК, поэтому там у Вас вопросов нет.  Универсальным способом решить этот вопрос можно так: вычислять значение констатны внешними инструментами и подставлять значение при сборке через ключ -D. Тогда и вычисление гарантировано будет происходить на этапе сборки, и вопросы сложности выражения и точности вычислений решаются независимо от возможностей препроцессора и компилятора.
--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
|
|
|
|
|
Oct 3 2006, 06:46
|
Местный
  
Группа: Участник
Сообщений: 416
Регистрация: 18-04-06
Из: Челябинск
Пользователь №: 16 219

|
Цитата(dxp @ Oct 3 2006, 06:35)  Цитата(SasaVitebsk @ Oct 2 2006, 22:48)  Это приятно. У меня был ассемблер х51. Так вот он это умел делать.
Это частные особенности того ассемблера. По Стандарту С/С++ компилятор не обязан рассчитывать такие выражения. Цитата(SasaVitebsk @ Oct 2 2006, 22:48)  А на AVR Studio столкнулся с потерей точности. Надо формулу правильно писать. А то сначала поделит (отбросит лишнее) потом умножит, - ну и привет.  Это Вы, наверное, препроцессор имеете в виду? Он - да, на этапе компиляции рассчитывает. Но только в целых числах и только в 32-х битах. Часто этого оказывается достаточно. Только препроцессор не константы инициализирует, а макросы. А с константами уже работает компилятор. Но это уже не следующем этапе. И вот компилятор ничего вычислять на этапе компиляции не обязан. Максимум он может прооптимизировать инициализатор, если там не используются, например, функции типа синуса или логарифма. Цитата(SasaVitebsk @ Oct 2 2006, 22:48)  Как правило компиляторы PC поступаю правильно. То есть определяют если выражение константное, то сразу подставляют его значение. Компиляторы PC делают это на рантайме (при загрузке программы), как и всякие другие компиляторы С/С++. Просто рантайм у PC намного дешевле, чем у МК, поэтому там у Вас вопросов нет.  Если быть точным, то препроцессор не производит каких-либо вычислений. Функцией препроцессора является простая замена одного фрагмента текста на другой. Все вычисления делаются компилятором. И, опять же, следует иметь в виду, что вычисления производятся с фиксированной точкой (если не указано явно), и все константы имеют тип int. Можно явным образом определить константы как unsigned, long или float. Если производятся вычисления констант целого типа, то нужно выбирать порядок вычисления таким образом, чтобы потеря точности была минимальной. Т.е. при выполнении операции деления следует стремится к тому, чтобы делимое было как можно больше, а делитель был как можно меньше.
|
|
|
|
|
Oct 3 2006, 10:18
|
Гуру
     
Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521

|
Цитата(IgorKossak @ Oct 3 2006, 12:48)  В теме имелось в виду не то, кто чем и как занимается (компилятор или препроцессор), а как вычислить константу при помощи сложной формулы, содержащей функции, на С. Так вот ответ - никак. Ибо вместо желаемой подстановки константного значения будет вызываться функция. В плане вычисления констант компилятор С достаточно беден. Это не FORTH, где такие вычисления возможны. Варианты обходных манёвров здесь уже приводились. Тем не менее спасибо всем. Мне было очень интересно узнать данные подробности. Это даёт некоторое понимание происходящего. Я уже понял что препроцессор просто подставляет (понятно из ошибок). Но мне кажется (хотя вопрос и риторический) что не правильно вставлять формулу в код программы, если её значение можно сразу вычислить на этапе компиляции. О какой после этого оптимизации можно говорить. По-моему где то читал, что всётаки какие-то из компиляторов так и поступают. А может мне приснилось. Ну чтож, раз мы не можем повлиять на процесс, то надо принять его как должное.
|
|
|
|
|
Oct 3 2006, 12:45
|
Местный
  
Группа: Участник
Сообщений: 416
Регистрация: 18-04-06
Из: Челябинск
Пользователь №: 16 219

|
Цитата(SasaVitebsk @ Oct 3 2006, 13:18)  Тем не менее спасибо всем. Мне было очень интересно узнать данные подробности. Это даёт некоторое понимание происходящего. Я уже понял что препроцессор просто подставляет (понятно из ошибок). Но мне кажется (хотя вопрос и риторический) что не правильно вставлять формулу в код программы, если её значение можно сразу вычислить на этапе компиляции. О какой после этого оптимизации можно говорить. По-моему где то читал, что всётаки какие-то из компиляторов так и поступают. А может мне приснилось. Ну чтож, раз мы не можем повлиять на процесс, то надо принять его как должное.  Все дело в том, что идентификатор функции (или переменной) может быть выбран программистом произвольно, и в общем случае компилятор не обязан знать назначение этой функции и ее расположение (в библиотеке исполнюящей системы (run time library), или в каком-либо программном модуле проекта). Здесь программисту предоставлена полная свобода в выборе идентификаторов. Соответственно, свобода компилятора получается крайне ограниченной. Поэтому никаких вычислений значений каких-либо функций компилятором не производится.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|