цифровая электроника
вычислительная техника
встраиваемые системы

 
» » Встроенные функции в C и C++

Встроенные функции в C и C++

Автор: Mike(admin) от 14-11-2013, 14:16

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


Основы принципа встраивания функций


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


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


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


Автоматическое встраивание


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


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


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


Встроенные функции в C++


Хотя современные компиляторы языка C поддерживают встроенные функции, все же такая особенность изначально появилась в C++. Существуют два способа сообщить компилятору, что встраивание функций может быть желательно: с помощью ключевых слов inline и с помощью функций-членов класса.


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


Хотя это ключевое слово кажется чрезвычайно полезным, оно таит в себе скрытую опасность, так как может привести к чрезмерному потреблению памяти:


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

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

Функции-члены класса. В C++ класс (и, по сути, структура) может включать в себя и функции, и код. Существуют два способа определения функций-членов. Код может быть включен в определении класса, или функция-член может быть определена и объявлена где-то снаружи.


Ниже функция foo() объявляется каждым из возможных способов. Наблюдается интересная разница между этими двумя подходами: определение в классе советует компилятору встроить функцию, при внешнем определении для достижения того же результата потребуется модификатор inline. В этом примере T1::foo() встраивается (или с большой вероятностью может быть встроена), а T2::foo() нет (или скорее всего не будет встроена).



class T1
{
public:
void foo()
{
...
}
};

class T2
{
public:
void foo();
};

void T2::foo()
{
...
}

Заключение


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




Перевод © digitrode.ru


<Источник>


Теги: язык C



Уважаемый посетитель, Вы зашли на сайт как незарегистрированный пользователь.
Мы рекомендуем Вам зарегистрироваться либо войти на сайт под своим именем.

Комментарии:

Оставить комментарий