AVR GCC&IAR

Loading thread data ...
Reply to
Leha Bishletov
Reply to
Leha Bishletov
Reply to
Maxim Polyanskiy
Reply to
Maxim Polyanskiy
16-Jan-04 17:38 Yuriy K wrote to Harry Zhurov:

HZ>> int a; HZ>> int f() { a++; return a; }; HZ>> void slon() {int b = SQUARE(f());} HZ>> Получишь совсем не то, что ожидаешь! И граблей таких там море.

YK> Классический случай function with side effects. Грабли здесь всегда YK> можно найти, особенно если их искать. Кстати, Harry, вдогонку:

void foo( int a, int b);

foo( f(), f());

при твоей f() тоже приведёт к неопределённому результату, хотя никакими макросами тут не пахнет -- одни функции. Грабли обеспечены даже если этот код будет компилироваться в режиме C++ :-) Достаточно забыть, что f() имеет side effects.

wbr,

Reply to
Oleksandr Redchuk
16-Jan-04 05:57 Harry Zhurov wrote to Yuriy K:

HZ>>> имеем очень простой макрос: HZ>>> #define SQUARE(x) x*x

HZ> Я тебе принцип продемонстрировал, а ты в частности лезешь... Ладно, HZ> хочешь быть сам себе злобным буратиной - будь!

YK>> #define SQUARE(x) ((x)*(x))

YK>> Как ты справедливо заметил, об этом написано во всех учебниках.

HZ> В учебниках не этот пример приводится, а пример с низкоприоритетными HZ> операциями типа: #define doubling(x) x+x Ну не помню, в каких учебниках что приводится (+ или *), больно давно читал. Но про неожиданные эффекты в макросах из-за отсутствия скобок вокруг аргументов и из-за подсовывания туда вещей с "самостоятельными" побочными эффектами предупреждают громко.

HZ> int a; HZ> int f() { a++; return a; };

HZ> void slon() HZ> { HZ> int b = SQUARE(f()); HZ> }

HZ> Получишь совсем не то, что ожидаешь! Как в таких случаях принято говоить, ССЗБ :-)

HZ> И граблей таких там море. И замаешься HZ> обо всем помнить и "писать аккуратно". Тем более, что и так есть на что HZ> потратить усилия и аккуратность. Да, писание на С требует бОльшей внимательности, чем на C++. Что не означает, кстати, что на С++ писать легче :-) Честно говоря, при элементарной внимательности макросы - это отнюдь не то, на чём можнонарваться на грабли. А если быть забывчивым, то можно сказать new и не сказать потом delete - и чем тут спасёт отсутствие макросов?

Я не припомню в последние много лет проблем со своими макросами. Да и в первые много лет тоже :-) Правда, у меня есть некоторые привычки. Скажем, макрос, в который нельзя совать выражения с побочными эффектами у меня всегда большими буквами, а в который можно (т.е. ведёт себя "как функция") - и обозван в том же стиле, что и функция.

YK>> Заметим, что граблей совсем не возникает если не использовать выражения с YK>> side effects в аргументах макроса, что само по себе хороший тон.

HZ> А где там выражение с side effects? Инкремент аргумента, что ли? Тут Да. b++ это выражение имеющее значение b и побочный эффект в виде инкремента этого b. ++b это выражение имеющее значение b+1 и побочный эффект в виде инкремента этого b. И об этом предупреждают там же (в учебнниках по С).

HZ> все HZ> нормально и четко определено с точки зрения языка - создается копия 'b', HZ> потом 'b' инкрементируется, Как это реализовано -- по барабану. Главное то, что b++ это выражение. Если ты напишешь a = c*b++ + d*b++; ты огребёшь по полной пронграмме именно на том, что b++ это подвыражение с побочным эффектом.

YK>> Точнее они подтверждают, что макросы нужно писать и использовать YK>> _аккуратно_. О чем я и говорил.

HZ> Т.е. их лучше не использовать при любой возможности. А как с goto? :-)

"Лучше не использовать без особой надобности"

"лучше не использовать при любой возможности" (имеется ввиду при наличии возможности их не использовать)

"лучше не использовать вообще никогда"

это "три большие разницы". Ты вроде как говоришь вторую, но твои аргументы защищают третью. А в рамках языка С справедлива, IMHO, первая.

HZ> неправоте - твое право, но у меня более нет ни сил, ни времени, ни HZ> желания участвовать в этом. Язык C существует и будет ещё долго существовать вне зависимости от твоих убеждений. И в рамках этого языка макросы занимают своё место по праву. И используются они отнюдь не для SQUARE() :-), а ещё и в таких местах:

#define _E(ERRCODE) ERRCODE, #ERRCODE

struct { int code; char *name; } errCodeNames[] = { _E( ERR_NONE), _E( ERR_TOUT), _E( ERR_OTHER) };

#undef _E

Покажи мне грабли в макросах

#define out_b( port, byte) ((port)=(byte)) #define in_b( port) (port) #define out_w( port, byte) ((port)=(byte)) #define in_w( port) (port)

котрые использовались для того, чтобы одни и те же исходники компилировались и IAR C/AVR, и avr-gcc 2.95 (только тройка научилась работать с PORT = VAL).

Чем тебе не нравятся

#define _setL(var,bit) (var)&=~(1<<bit) #define _setH(var,bit) (var)|=(1<<bit) #define _set(var,bit,val) _set##val(var,bit) #define on(x) _set (x) #define SET _setH

#define _clrL(var,bit) (var)|=(1<<bit) #define _clrH(var,bit) (var)&=~(1<<bit) #define _clr(var,bit,val) _clr##val(var,bit) #define off(x) _clr (x) #define CLR _clrH

#define _bitL(var,bit) (!((var)&(1<<bit))) #define _bitH(var,bit) ((var)&(1<<bit)) #define _bit(var,bit,val) _bit##val(var,bit) #define signal(x) _bit (x) #define BIT _bitH

от Аскольда Волкова и, главное, КАК ты предлагаешь заменить это на inline-функции?

#define AT45_CS PORTB,5,L #define DS1302_CS PORTB,6,H

off(AT45_CS); on(DS1302_CS);

Можно, конечно, написать по паре inline-функций на каждую ногу, inline void At45cs_on(void) { PORTB &= ~(1<<5); } inline void At45cs_off(void) { PORTB |= (1<<5); } inline void DS1302cs_on(void) { PORTB |= (1<<6); } inline void DS1302cs_off(void) { PORTB &= ~(1<<6); }

Но только если предположить за программистом такую же невнимательность и забывчивость, которую ты предполагаешь за использующими #define, то при любой модификации или в одной их них номер вывода забудут поменять, или в другой -- заменить |= на &= ~ и легче от того, что это функции, а не макросы -- не станет.

В C99 появился inline (в GNU C он давно есть) и я с удовольствием буду использовать inline там, где сочту удобным. Но там где удобнее #define - буду использовать #define.

wbr, p.s. почему-то когда говорят, что C и #define использовать _МОЖНО_ ты слышишь что _НУЖНО_ИСПОЛЬЗОВАТЬ_ТОЛЬКО_ИХ_ и споришь с этим своим слышением.

Reply to
Oleksandr Redchuk
Reply to
Maxim Polyanskiy
Reply to
Maxim Polyanskiy
Reply to
Andrew Gooskov
Reply to
Maxim Polyanskiy

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.