LINUX.ORG.RU

[C99][Теория]

 


0

0

Есть в С99 inline функции, чем они принципиально (кроме большей гибкости) отличаются от макроса?

Я додумался, что ничем.

Задам вопрос иначе, в каком случае выгоднее для производительности (скорости работы приложения) написать макросс, чем использовать inline функцию?

(естественно для чего-то слождее max\min)

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

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

trex6 ★★★★★
()

inline это только рекомндация для компилятора, чтобы он её рассмотрел в роли подставляемой.

Boy_from_Jungle ★★★★
()

>Есть в С99 inline функции, чем они принципиально (кроме большей гибкости) отличаются от макроса?

Ну насчет большей гибкости у inline функции я бы поспорил, но ИМХО inline лучше в большинстве случаев. Это связано с тем, что каждая не просто «кусок кода», но это ещё и «соглашение» об типах используемых параметров. Также функции лучше осуществляют декомпозицию задачи. Поведение функции более «предсказуемо» чем макрос для того кто эту функцию не писал, но зато использует.

в каком случае выгоднее для производительности (скорости работы приложения) написать макросс

Вроде разницы нет.

pathfinder ★★★★
()

>Задам вопрос иначе, в каком случае выгоднее для производительности (скорости работы приложения) написать макросс, чем использовать inline функцию?

Вроде нет такого случая. Могу только пример наборот привести

#define sqr(a) ((a)*(a))

hired777
()
Ответ на: комментарий от pathfinder

>>#define sqr(a) ((a)*(a))

Очень интересно. И за счет чего достигается выигрыш по производительности?

Очевидно если написать sqr(very_long_computation(123)), то функция very_long_computation будет вызвана 2 раза.

nozh
()
Ответ на: комментарий от nozh

>Очевидно если написать sqr(very_long_computation(123)), то функция very_long_computation будет вызвана 2 раза.

Ну да в общем верно. Хотя неизвестно что там оптимизатор может начудить.

pathfinder ★★★★
()
Ответ на: комментарий от pathfinder

оптимизатор уже ничего не начудит, он получит ((very_long_computation(123))*(very_long_computation(123))) от препроцессора и второй вызов very_long_computation убрать не сможет.

shuthdar ★★★
()

Макросы в Си надо применять только для условной компиляции. Все другие их применения недопустимы, вредны и ошибочны.

anonymous
()
Ответ на: комментарий от nozh

>Очевидно если написать sqr(very_long_computation(123)), то функция very_long_computation будет вызвана 2 раза.

для меня, нуба, не очевивидно. почему?

Turbid ★★★★★
()
Ответ на: комментарий от shuthdar

>оптимизатор уже ничего не начудит, он получит ((very_long_computation(123))*(very_long_computation(123))) от препроцессора и второй вызов very_long_computation убрать не сможет.

Я не силен в теории современных оптимизаторов. А что? Они не могут догадываться по коду некоторых функций, что они «чистые»? И потом пользоваться этим для оптимизации.

pathfinder ★★★★
()
Ответ на: комментарий от pathfinder

А если функция не чистая - тогда вообще ахтунг.

За использование макросов в Си не по назначению надо отрубать гениталии.

anonymous
()
Ответ на: комментарий от pathfinder

>Они не могут догадываться по коду некоторых функций, что они «чистые»?

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

shuthdar ★★★
()
Ответ на: комментарий от pathfinder

>Они не могут догадываться по коду некоторых функций, что они «чистые»?

Это принципиально возможно только в том случае, если вызов функции и ее определение находятся в одном файле. Правда gcc поддерживает атрибут pure для чистых функций, тогда можно иметь определение и использование чистой функции в разных файлах при сохранении возможнонсти оптимизации (http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html)

anonymous
()

>Есть в С99 inline функции, чем они принципиально (кроме большей гибкости) отличаются от макроса?

#include <stdio.h>
#define MAX(a,b) ((a) > (b) ? (a) : (b))
static int max(int a,int b) {
  return a > b ? a : b;
}

int main()
{
  int a = 11, b = 10;
  printf ("MAX = %d\n", MAX(a--,b));
  printf("\ta = %d, b = %d\n", a, b);
  a = 11; b = 10;
  printf ("max = %d\n", a, b, max(a--,b));
  printf("\ta = %d, b = %d\n", a, b);
  return 0;
}

Ну и прочие мелочи вроде конфликтов имен локальных переменных и т. д. и т. п.

linuxfan
()
Ответ на: комментарий от hired777

> #define sqr(a) ((a)*(a))

Весьма оригинально. Зря вы школу сачковали - там рассказывали, что такое квадратный корень.

andreyu ★★★★★
()
Ответ на: комментарий от andreyu

> Весьма оригинально. Зря вы школу сачковали - там рассказывали, что такое квадратный корень.

sqr вроде в паскале - квадрат, а корень - это sqrt( и не только в паскале )

lester ★★★★
()
Ответ на: комментарий от andreyu

Поумничал, школота? sqr всю жизнь квадратом был. Корень тебе приснился.

anonymous
()
Ответ на: комментарий от shuthdar

в случае с Си чистота не определима

Мне все равно непонятно. Оптимизатор компилятора всегда работает с конкретными частными случаями. Можешь объяснить почему в данном примере определение чистоты функции невозможно.

#include <stdio.h>

inline double f(double x)
{
  return 3.0*x*x+5.0*x+7.0;
}

int main()
{
... //Здесь некий код

  double y1 = f(x);
  double y2 = f(x);

... //Здесь некий код
}
pathfinder ★★★★
()

ЕМНИП, не любой код компилятор сделает inline'ом (это лишь рекомендация).

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

Davidov ★★★★
()

[code=c]#include <stdio.h> #include <string.h>

#define foreach(s, c) c=0; for (int i=0, c=s[0]; i<strlen(s); c=s[++i])

int main() { char c; foreach(«word», c) printf(«%c\n», c); } [/code]

Davidov ★★★★
()
Ответ на: комментарий от Davidov

ЕМНИП, не любой код компилятор сделает inline'ом (это лишь рекомендация).

И я о том же, нужно attribute ей давать чтобы всегда подставлялась.

Boy_from_Jungle ★★★★
()
Ответ на: комментарий от Boy_from_Jungle

> Почему?! Зачем?! Это чистая функция.

потому-что если человеку наплевать на быстродействие - то на С ему программировать не рекомендуется, есть море безопасных и удобных языков

lester ★★★★
()
Ответ на: комментарий от Davidov

Речь о том, чтобы заменить i<strlen(s) на s[i].

понял, изначально я не за это завёл речь.

Boy_from_Jungle ★★★★
()
Ответ на: комментарий от pathfinder

Я вообще на C последнее время не пишу. Последний раз макросы использовал для вывода отладочных сообщений. Наверное, хорошо ассерты при помощи макросов делать (если они ещё не появились в самом языке, не слежу).

Говорят, что первую версию плюсов Страуструп сделал как раз при помощи макросов.

В общем, это скорее теоретический ответ, чем реально полезная конструкция.

Davidov ★★★★
()
Ответ на: комментарий от Boy_from_Jungle

c=s[0] на c=s;

Да, можно. С точки зрения понимания так лучше, да.

Я думаю, что можно придумать ситуацию, когда strlen(s) будет работать медленнее (плохой компилятор, вынужденные требования -O0, собственная реализация strlen).

Davidov ★★★★
()

> чем они принципиально отличаются от макроса?

тем, что их аргументы вычисляются перед вызовом.

korvin_ ★★★★★
()
Ответ на: комментарий от Boy_from_Jungle

Может ты прочтёшь, на что я отвечал?

LamerOk ★★★★★
()
Ответ на: комментарий от xydo

>хотя это gcc-зм

а работоспособность такой конструкции зависит от конкретной реализации компилятора? В не-гцц может и не сработать?

Corey
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.