LINUX.ORG.RU

С макросы


0

0

Как заставить С-шный макрос возвращать значенние как функтция.

Например:

#define MY_SUPER_PUPER_MACRO(a,c) ....

...

var=MY_SUPER_PUPER_MACRO(var1,var2);

...

В этом случае я хочу, чтобы переменной var было присвоено значение, которое является результатом вычисления MY_SUPER_PUPER_MACRO(var1,var2). А данный макрос не обязательно однострочный... В смысле может быть последовательностю нескольких команд

> Как заставить С-шный макрос возвращать значенние как функтция.

#define M(a, b) (a + b)

> В смысле может быть последовательностю нескольких команд

Это только расширения GCC умеют

#define M(a, b) ({ in t1 = f1(a); int t2 = f2(b); f3(t1 + t2) })

tailgunner ★★★★★
()

Очевидно, анонимус просто не понял, как работают макросы..

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

>Это только расширения GCC умеют

>#define M(a, b) ({ in t1 = f1(a); int t2 = f2(b); f3(t1 + t2) })

Ага. Где-то в исходниках ядра такое видел.

korey4ik
() автор топика
Ответ на: комментарий от jtootf

> а зачем ?

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

korey4ik
() автор топика
Ответ на: комментарий от Legioner

> Иногда через запятую можно. Про неё многие забывают.

Еще иногда можно таким вот извращенным способом:

#include <stdio.h>

typedef void* (*anyfunc_t)(void*, ...);

anyfunc_t anyfunc(void* x)
{
        return x; 
}

#define foo(a, b) anyfunc(puts)(a, puts(b))

int main()
{
        foo("a", "b");
}

Я специально включил <stdio.h>, чтобы показать приведение типов 
функций. При попытке использовать непосрежственное приведение puts
к типу anyfunc_t gcc говорит:

foo.c: В функции ‘main’
foo.c:14: предупреждение: вызов функции через несовместимый тип
foo.c:14: замечание: при достижении этого кода выполнение программы завершится аварийно

Begemoth ★★★★★
()

На inline ф-ии есть серьезные ограничения. Они не всегда будут вставляться в текст, как макросы.

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

> Стыдись, плюсофил:

Чего именно мне стыдится? Что ты написал макрос, который при использовании обязательно брать в фигурные скобки и которы при использовании в else будет молча порождать неправильный код?

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

> Это смотря где и зачем использовать многострочные макросы.

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

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

> На inline ф-ии есть серьезные ограничения. Они не всегда будут вставляться в текст, как макросы.

А есть случаи когда обязательно необходима именно прямая вставка и недостаточно предписываемого стандартом: "Making a function an inline function suggests that calls to the function be as fast as possible"?

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

Поведение компилятора при высоких оптимизациях не очень предсказуемо.

У ГЦЦ есть ключики (--param), позволяющие заставить его все синлайнить. Я однажды поиграл параметрами типа large-function-growth и inline-unit-growt, пока оно не перестало говорить, что чего-то не синлайнило (ключик -Winline нужен). В результате программа оказалась толще и работала медленнее...

Die-Hard ★★★★★
()

хм, вообще проще сделать так:

#define my_macro_func(i1, i2, /* out */ var) \
do {\
*var = i1 + i2;\
*var <<= 1; \
.. anything else ...; \
} while(0);

int var;
my_macro_func(1, 2, &var);

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

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

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

Вылезайте из каменного века, на дворе c99.

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

> И попрошу не опускаться до возрастной дискриминации.

Ты так и не сказал, за что мне должно быть стыдно.

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

> ';' после while не ставят

бред. не ставят при написании такого паттерна макроса только из-за "стилистических предпочтений", do { code; } while(0);;;;;;;;;;;;;... continue as long as u want ...;;;;;;; - абсолютно приемлемая конструкция.

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

>> ';' после while не ставят

>бред. не ставят при написании такого паттерна макроса только из-за "стилистических предпочтений"

Про "стилистические предпочтения" - бред, согласен. Перестань бредить.

> do { code; } while(0);;;;;;;;;;;;;... continue as long as u want ...;;;;;;; - абсолютно приемлемая конструкция.

Синтаксически правильная. Теперь представь, что поставил ее после if ()

P.S. вы с xTERM не на одном курсе учитесь?

tailgunner ★★★★★
()
Ответ на: комментарий от Die-Hard

> В результате программа оказалась толще и работала медленнее...

То что распухла - это понятно. А за счет чего могла стать медленнее?

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

> То что распухла - это понятно. А за счет чего могла стать медленнее?

распухание влечет более частые промахи в кэш и снижение правильных предсказаний условных переходов.

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

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

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

> Но значит тот же эффект мы получим бездумно используя "оптимизирующие" макросы.

Если что угодно использовать "бездумно" - хорошего ничего не получится. Но у "оптимизирующих" макросов есть таки некоторые "плюсы": параметры не передаются через стек (а их может быть много), часто среди параметров есть куски кода - в функциональном варианте это будет передача/вызов замыканий - тоже не бесплатная операция. И не надо забывать про "читабельность кода" и его количество.

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

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

Со времен Кена Томпсона, затраты на вызов функций в Си сильно .. ВЫРОСЛИ (я не шучу).

Сейчас неудачное действие может сбросить весь конвейр CPU, а если еще не угодали с данными, которые нужно было prefetch-ить, то это многие сотни тактов ожидания, пока конвер снова заполнится.

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

> Сейчас неудачное действие может сбросить весь конвейр CPU

Инструкции вызова вроде бы не относятся к таким действиям - они вполне успешно предсказываются.

> а если еще не угодали с данными, которые нужно было prefetch-ить

Тоже не имеет прямого отношения к тому, встроен код в место вызова или нет.

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

> Инструкции вызова вроде бы не относятся к таким действиям - они вполне успешно предсказываются.

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

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

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

Макрос или inline-функция отличаются от обычной функции только инструкциями вызова, так что "дугое действие" (если оно есть) одинаково повредит и inline-, и обычной функции.

> или пример хороший -- вызов через указатель

Это не случай inline/макроса :)

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

> Макрос или inline-функция отличаются от обычной функции только инструкциями вызова, так что "дугое действие" (если оно есть) одинаково повредит и inline-, и обычной функции.

Ну, вообще я против inline ничего вроде не говорил, я про обычные, неинлайнящиеся.

P.S. Касательно инлайнов и оптимизаций: в порядке изучения ADA (давно дело было), написал как-то generic модуль, "удваивающий" точность числа, т.е. если ему "вход" подать Int32, то на выходе получаем Int64, для которого определены все те-же операции базовые арифметические. Я таким образом до Int2048 доходил, это, если на язык плюсовых шаблонов, было бы нечто вроде

typedef double_prec< double_prec< double_prec< double_prec< .... < int >>> ... >>> int2048;

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

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

P.P.S. кому интересно: операция деления в итоге работала _НЕ_ быстрее, чем деление вручную написанное для IntXXX постороенном иначально на векторе Int32-ых, где размер вектора - параметр модуля(или шаблона).

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

~/tmp % cat test.c
#include <stdio.h>

int main(void)
{
  int i = 3;
  do
    {
      printf ("test\n");
      --i;
    }while (i > 0)

  return 0;
}

/tmp % gcc test.c -o test
test.c: In function ‘main’:
test.c:12: error: expected ‘;’ before ‘return’

так а чём это мы?

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

> Это не мы, это ты :)

я думаю ты не будешь отрицать что это:

>> хм, вообще проще сделать так:

> ';' после while не ставят

ты написал? ;)

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

> так а чём это мы?

Возможно о том, что вам стоит научится сначала смотреть на контекст, в котором сказана фраза? :)

Речь шла о

#define SomeStuppidPureCMacroForBastardsWhoStillDoesntBelivesToCompilerOptimization(x, y) do { .... } while (0)

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

А вообще я тебя понимаю... заработаешься так... сборная россии проиграет... челюсть ноет после похода к стоматолагу... ещё и не такое напишешь с горича :)

всякий может спутать синтаксис

while (..) { ... }

и

do { ... } while (...);

:)

в любом случае - relax! =)

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

Контекст я понимаю прекрасно... но фраза явно звучала вне контекста

> ';' после while не _ставят_

это немного отличается от "';' после while в данном случае можно не ставить"

;)

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

>>> хм, вообще проще сделать так:

>> ';' после while не ставят

> ты написал? ;)

Не буду. А причем здесь то, что написал ты? Выдано нормальное, понятное сообщение об ошибке - "отсуствует ';'". Теперь сравни с тем, что говорит компилятор на такое:

int f(int a)
{
if (a)
do { return 1; } while(0);;;;;
else
return 1;
}

И подумай, что будет, если do { } while(0);;;;; поместить в макрос. Подсказка - компилятор ругнется на конструкцию, которая синтаксически выглядит абсолютно верной.

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

> Контекст я понимаю прекрасно... но фраза явно звучала вне контекста

как раз в контексте :)

xxx> хм, вообще проще сделать так: 
xxx>
xxx> #define my_macro_func(i1, i2, /* out */ var) \ 
xxx> do {\ 
xxx> *var = i1 + i2;\ 
xxx> *var <<= 1; \ 
xxx> .. anything else ...; \ 
xxx> } while(0); 
xxx> 
xxx> int var; 
xxx> my_macro_func(1, 2, &var);

yyy> ';' после while не ставят

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

Некоторые люди не читают сообщений целиком, а жаль :)

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