Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Опасные определения
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > IAR
ivainc1789
В программе есть описания:

#define BIT(x) (1 << (x))
#define SETBIT(x,y) (x |= (1<<y)) // Set bit y in byte x
#define SETBITS(x,y) (x |= (y)) // Set bits y in byte x

Соответственно при написании исходных текстов пользователь может забыть как правильно использовать эти определения и написать примерно так:

SETBIT(TIMSK,TOIE1);
SETBITS(TIMSK,TOIE1+TOIE0);

Очевидно, оба предложения валидны с точки зрения компилятора при использовании стандартных определений битов (через цифры 7...0). Однако второе предложение является ошибочным. Нужно правильно записать так:

SETBITS(TIMSK,BIT(TOIE1)+BIT(TOIE0));

Хотелось бы сделать так, чтобы либо компилятор выдавал сообщение об ошибке, или переписать определение для SETBITS, чтобы оно имело бОльшую "защиту от дурака".
Как это разумнее сделать в IAR EWAVR?
Непомнящий Евгений
Цитата(ivainc1789 @ Sep 7 2007, 18:44) *
#define SETBITS(x,y) (x |= (y)) // Set bits y in byte x


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

Лично я пользуюсь макросами вида:
Код
#define BIT(n) (1<<(n))
#define BIT2(b1, b2) (BIT(b1)|BIT(b2))
#define BIT3(b1, b2, b3) (BIT2(b1,b2)|BIT(b3))
#define BIT4(b1, b2, b3, b4) (BIT3(b1,b2,b3)|BIT(b4))
#define BIT5(b1, b2, b3, b4, b5) (BIT4(b1,b2,b3,b4)|BIT(b5))
#define BIT6(b1, b2, b3, b4, b5, b6) (BIT5(b1,b2,b3,b4,b5)|BIT(b6))
#define BIT7(b1, b2, b3, b4, b5, b6, b7) (BIT6(b1,b2,b3,b4,b5,b6)|BIT(b7))

#define SETBIT(p,n) (p)|=BIT(n)


Если вам нужен SETBITS, то насоздавайте кучу макросов SETBIT2 .. 7
Неудобство - надо указывать правильное число. Если укажите неправильное - получите ошибку компиляции. В принципе, не сильно напрягает...
zltigo
Цитата(ivainc1789 @ Sep 7 2007, 17:44) *
SETBITS(TIMSK,BIT(TOIE1)+BIT(TOIE0));
Как это разумнее сделать в IAR EWAVR?

Будьте естественней:
TIMSK |= TIMSK_TOIE0 | TIMSK_TOIE1;
Выражение короче, абсолютно читабельно без вникания в макросы и чего еще сложнее без вникания в чуждую логику. Биты поименованы с названием регистра и по крайней мере несоответствие типа
TIMSK |= TIMSK_TOIE0 | FUKA_TOLL7; Есть шанс заметить глазами в отличие от
SETBITS(TIMSK,BIT(TOIE1)+BIT(TOLL7)); Которое без поллитра не разберешь и впридачу надо помнить, что TOLL7 никакого отношения к регистру TIMSK не имеет,
дабы не ошибиться.
Не выпендривайтесь с макросами там, где они без надобности.
ivainc1789
Цитата(zltigo @ Sep 7 2007, 21:46) *
Будьте естественней:
TIMSK |= TIMSK_TOIE0 | TIMSK_TOIE1;


Warning[Pa082]: undefined behavior: the order of volatile accesses is undefined in this statement
zltigo
Цитата(ivainc1789 @ Sep 7 2007, 21:23) *
Warning[Pa082]: undefined behavior: the order of volatile accesses is undefined in this statement

А это уже не проблема этого выражения - чего-то Вы в #define понаписали.
singlskv
Цитата(ivainc1789 @ Sep 7 2007, 18:44) *
В программе есть описания:

#define BIT(x) (1 << (x))
#define SETBIT(x,y) (x |= (1<<y)) // Set bit y in byte x
#define SETBITS(x,y) (x |= (y)) // Set bits y in byte x

Соответственно при написании исходных текстов пользователь может забыть как правильно использовать эти определения и написать примерно так:

SETBIT(TIMSK,TOIE1);
SETBITS(TIMSK,TOIE1+TOIE0);

Я обычно делаю так
#define TOIE1_MASK (1<<TOIE1)
#define TOIE0_MASK (1<<TOIE0)
#define TOIE01_MASK (TOIE1_MASK | TOIE1_MASK)

Если лень писать каждый раз _MASK то заменяем его на _M, типа TOIE1_M, ну или как-то еще,
удобнее автору.

количество вариантов значений которые нужно пинать в регистр обычно ограничено 2-3
по этому можно писать и так:
#define TIMSK_M1 (1<<TOIE1)
#define TIMSK_M2 ((1<<TOIE1) | (1<<TOIE0))

ну и применение
TIMSK |= TIMSK_Mx;
Цитата
Warning[Pa082]: undefined behavior: the order of volatile accesses is undefined in this statement
Скобочки где-то забыли, например при 1<<yy
у << маленький приоритет
zltigo
Цитата(singlskv @ Sep 7 2007, 22:14) *
у << маленький приоритет

Скобочки, действительно, абсолютно обязательны, но вот приоритет у поразрядных сдвигов самый высокий среди упомяутых выше операций, и даже разворот в такое мутное выражение
TIMSK |= 1<<2 | 1<<4;
дает вполне однозначный результат.
singlskv
Цитата(zltigo @ Sep 7 2007, 23:56) *
Скобочки, действительно, абсолютно обязательны, но вот приоритет у поразрядных сдвигов самый высокий среди упомяутых выше операций, и даже разворот в такое мутное выражение
TIMSK |= 1<<2 | 1<<4;
дает вполне однозначный результат.
Ну конечно Вы правы... smile.gif
за исключением одного момента,
афтар почему-то в первоначальном посте указал нам что он предпочитает
использовать BIT(TOIE1)+BIT(TOIE0) вместо BIT(TOIE1)|BIT(TOIE0),
а у них уже разный приоритет относительно барикады (<<) smile.gif
zltigo
Цитата(singlskv @ Sep 7 2007, 23:06) *
а у них уже разный приоритет относительно барикады (<<) smile.gif

Тогда вилы smile.gif.
Хотя вообще '+' использовать последнее дело - при перекрытии битов, получить эффектов по полной программе можно. А оно это надо?
singlskv
Цитата(zltigo @ Sep 8 2007, 00:15) *
Тогда вилы smile.gif.
Поэтому и предлагаю сформулировать правило:
1<<XX ВСЕГДА ПИШИ В СКОБКАХ
сам пользуюсь и другим желаю, не пожалеете...
zltigo
Цитата(singlskv @ Sep 7 2007, 23:19) *
Поэтому и предлагаю сформулировать правило:
1<<XX ВСЕГДА ПИШИ В СКОБКАХ

Все строже - в макросах абсолютно все выражения и все аргументы всегда в скобках. Без вариантов!
Пример:
#define func( a, x ) ((a)+((x)<<2))
singlskv
Цитата(zltigo @ Sep 8 2007, 00:38) *
Все строже - в макросах абсолютно все выражения и все аргументы всегда в скобках. Без вариантов!
Пример:
#define func( a, x ) ((a)+((x)<<2))

+1
В макросах - без вариантов

1<<XX ВСЕГДА ПИШИ В СКОБКАХ
во всех вариантах без разбору,
очень помагает для сохранения нервной системы smile.gif
zltigo
Цитата(singlskv @ Sep 7 2007, 23:48) *
1<<XX ВСЕГДА ПИШИ В СКОБКАХ
во всех вариантах без разбору,
очень помагает для сохранения нервной системы smile.gif

Ну это Вы похоже как-то на грабли больно наступили smile.gif. Почему (1<<XX) "всегда" а например,
1 & XX
"не всегда"? Хотя второе много опаснее ввиду более низкого приоритета, не говоря уже о
1 | XX
или страшно сказать
XX |= 1
В общем думать надо всегда, ну и скобочки не жалеть, но ровно в меру! smile.gif тоже не помешает для читабельности.
ivainc1789
Мдя... А я уже было думал, что привык... Придется макросы переделать... С сабжевым вопросом потратил 4 часа, пока вспомнил свой SETBITS.
Всем большое спасибо...
singlskv
Цитата(zltigo @ Sep 8 2007, 00:58) *
Ну это Вы похоже как-то на грабли больно наступили
ага, наступал, просто большинство других вариантов или видны или ловятся компилятором
при неправильном использовании, а этот (<<) как раз из-за возможности пользовать
или + или | очень легко пропустить...
aaarrr
0xFF, но повод хороший. Не могу не поделиться замечательным макросом:
Код
#define    sizeof(x)    rand()

(с) ibash.org


UPD-Disclaimer: Данное макроопределение является т.н. шуткой. Использование данного макроса может привести к катастрофическим последствиям. Не используйте его, если полностью не уверены в своих действиях.
zltigo
Цитата(singlskv @ Sep 8 2007, 00:19) *
этот (<<) как раз из-за возможности пользовать
или + или | очень легко пропустить...

Повторяю. Как и любые другие, например, вышеприведенные с еще меньшими приоритетами.


Цитата(aaarrr @ Sep 8 2007, 01:08) *
Не могу не поделиться замечательным макросом...

Вы бы хоть улыбочек понапихали, а то народ здесь разный бывает - может получиться действительно "замечательно" smile.gif.
dxp
Цитата(aaarrr @ Sep 8 2007, 05:08) *
0xFF, но повод хороший. Не могу не поделиться замечательным макросом:
Код
#define    sizeof(x)    rand()

(с) ibash.org

Изумительный вариант для сюрпризов. Хоть бы уж так написали: SIZEOF(x).
alexander55
По поводу макросов могу сказать, не ленитесь побольшу скобок. Лишние никогда не мешают.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.