|
Опасные определения, приводят к катастрофе! |
|
|
|
Sep 7 2007, 14:44
|

Профессионал
    
Группа: Свой
Сообщений: 1 175
Регистрация: 5-01-05
Пользователь №: 1 807

|
В программе есть описания:
#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?
|
|
|
|
2 страниц
1 2 >
|
 |
Ответов
(1 - 14)
|
Sep 7 2007, 14:53
|
Знающий
   
Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153

|
Цитата(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 Неудобство - надо указывать правильное число. Если укажите неправильное - получите ошибку компиляции. В принципе, не сильно напрягает...
|
|
|
|
|
Sep 7 2007, 17:46
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(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 не имеет, дабы не ошибиться. Не выпендривайтесь с макросами там, где они без надобности.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Sep 7 2007, 19:14
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(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 у << маленький приоритет
|
|
|
|
|
Sep 7 2007, 19:56
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(singlskv @ Sep 7 2007, 22:14)  у << маленький приоритет Скобочки, действительно, абсолютно обязательны, но вот приоритет у поразрядных сдвигов самый высокий среди упомяутых выше операций, и даже разворот в такое мутное выражение TIMSK |= 1<<2 | 1<<4; дает вполне однозначный результат.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Sep 7 2007, 20:06
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(zltigo @ Sep 7 2007, 23:56)  Скобочки, действительно, абсолютно обязательны, но вот приоритет у поразрядных сдвигов самый высокий среди упомяутых выше операций, и даже разворот в такое мутное выражение TIMSK |= 1<<2 | 1<<4; дает вполне однозначный результат. Ну конечно Вы правы...  за исключением одного момента, афтар почему-то в первоначальном посте указал нам что он предпочитает использовать BIT(TOIE1)+BIT(TOIE0) вместо BIT(TOIE1)|BIT(TOIE0), а у них уже разный приоритет относительно барикады (<<)
|
|
|
|
|
Sep 7 2007, 20:19
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(zltigo @ Sep 8 2007, 00:15)  Тогда вилы  . Поэтому и предлагаю сформулировать правило: 1<<XX ВСЕГДА ПИШИ В СКОБКАХ сам пользуюсь и другим желаю, не пожалеете...
|
|
|
|
|
Sep 7 2007, 20:38
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(singlskv @ Sep 7 2007, 23:19)  Поэтому и предлагаю сформулировать правило: 1<<XX ВСЕГДА ПИШИ В СКОБКАХ Все строже - в макросах абсолютно все выражения и все аргументы всегда в скобках. Без вариантов! Пример: #define func( a, x ) ((a)+((x)<<2))
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Sep 7 2007, 20:48
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(zltigo @ Sep 8 2007, 00:38)  Все строже - в макросах абсолютно все выражения и все аргументы всегда в скобках. Без вариантов! Пример: #define func( a, x ) ((a)+((x)<<2)) +1 В макросах - без вариантов 1<<XX ВСЕГДА ПИШИ В СКОБКАХво всех вариантах без разбору, очень помагает для сохранения нервной системы
|
|
|
|
|
Sep 7 2007, 20:58
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(singlskv @ Sep 7 2007, 23:48)  1<<XX ВСЕГДА ПИШИ В СКОБКАХво всех вариантах без разбору, очень помагает для сохранения нервной системы  Ну это Вы похоже как-то на грабли больно наступили  . Почему (1<<XX) "всегда" а например, 1 & XX "не всегда"? Хотя второе много опаснее ввиду более низкого приоритета, не говоря уже о 1 | XX или страшно сказать XX |= 1 В общем думать надо всегда, ну и скобочки не жалеть, но ровно в меру!  тоже не помешает для читабельности.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Sep 7 2007, 21:19
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(zltigo @ Sep 8 2007, 00:58)  Ну это Вы похоже как-то на грабли больно наступили ага, наступал, просто большинство других вариантов или видны или ловятся компилятором при неправильном использовании, а этот (<<) как раз из-за возможности пользовать или + или | очень легко пропустить...
|
|
|
|
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|