реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Макрос инкремента с насыщением.
adnega
сообщение Dec 16 2012, 16:37
Сообщение #1


Гуру
******

Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702



Имеем gcc, пишем на C.

Задача: нужно написать некоторый макрос TICK(x), который бы при каждом вызове увеличивал переменную x на константу TO_TICK, но с учетом переполнения. Т.е. в случае если добавление TO_TICK вызовет переполнение, переменную x не изменять. Тип переменной x может быть любой целый (в том числе битовое поле).

Вариант 1:
Код
#define TICK(x) do{if((x + TO_TICK) > x) x += TO_TICK;}while(0)

не помогает, в случае знакового x и беззнакового TO_TICK. Видимо, (x + TO_TICK) считается беззнаковым и сравнивается с беззнаковым x.

Вариант 2:
Код
#define TICK2(x) do{typedef typeof(x) _tx; _tx _x = x; _x += TO_TICK; if(_x > x) x = _x;}while(0)

в принципе устраивает, но не работает с битовыми полями.

Параллельно узнал, что char без указания знаковости в "gcc version 4.8.0 20121121 (experimental) (Klen's GNU package (KGP) for ARM/elf platform)" является unsigned, хотя везде указывается диапазон char от -128 до 127. В "gcc версия 4.4.3 (GCC)" под Linux char знаковый.

Где нужно читать о типах данных C/GCC и приведении типов в арифметических операциях и операциях сравнения?
Кстати, при различных уровнях оптимизации результат тоже получаю различный. Хочется большей строгости...

Спасет ли переход на C++/GCC ?
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Dec 16 2012, 16:59
Сообщение #2


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Код
#define TICK(x) do{ unsigned char a = x+TO_TICK; if(a > TO_TICK) x=a;}while(0);

и вообще, какого икса дефайнить?
Код
static inline Tick(unsigned char *x)
{
unsigned char a = *x+TO_TICK;
if(a > TO_TICK) *x=a;
}


Сообщение отредактировал _Pasha - Dec 16 2012, 17:03
Go to the top of the page
 
+Quote Post
adnega
сообщение Dec 16 2012, 17:46
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702



Цитата(_Pasha @ Dec 16 2012, 20:59) *
и вообще, какого икса дефайнить?

Чтобы работало для разных типов на автомате.
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Dec 16 2012, 18:26
Сообщение #4


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(adnega @ Dec 16 2012, 20:46) *
Чтобы работало для разных типов на автомате.

Во! А теперь еще более интересный вопрос: у Вас "тикающий тип" - это одна сущность или много? Вернее, почему нельзя создать тип нужной размерности, скажем typedef unsigned int tick_t
Если на то есть причины, расскажите, плз, очень интересно.

Сообщение отредактировал _Pasha - Dec 16 2012, 18:27
Go to the top of the page
 
+Quote Post
adnega
сообщение Dec 16 2012, 18:29
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702



Цитата(_Pasha @ Dec 16 2012, 22:26) *
Во! А теперь еще более интересный вопрос: у Вас "тикающий тип" - это одна сущность или много? Вернее, почему нельзя создать тип нужной размерности, скажем typedef unsigned int tick_t
Если на то есть причины, расскажите, плз, очень интересно.

А то!
Раньше было много, сейчас, видимо, придется переходить на одну.
В целях экономии памяти использую различную разрядность "тикающих типов", в идеале вплоть до битовых полей.
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Dec 16 2012, 18:40
Сообщение #6


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(adnega @ Dec 16 2012, 21:29) *
А то!
Раньше было много, сейчас, видимо, придется переходить на одну.
В целях экономии памяти использую различную разрядность "тикающих типов", в идеале вплоть до битовых полей.

В таком случае (мсм) - проще функцию инлайновую завести, в аргументе const tick_t
Эффектов побочных от битовых полей не ожидается. При желании наплевать на контроль типов - обернуть функцию в дефайн. Вроде чуть больше строк, но просто и работать должно. Но не проверял laughing.gif

PS inline tick_t Tick(const tick_t tikable){}

Сообщение отредактировал _Pasha - Dec 16 2012, 18:49
Go to the top of the page
 
+Quote Post
adnega
сообщение Dec 16 2012, 18:52
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702



Цитата(adnega @ Dec 16 2012, 20:37) *
Вариант 2:
Код
#define TICK2(x) do{typedef typeof(x) _tx; _tx _x = x; _x += TO_TICK; if(_x > x) x = _x;}while(0)

в принципе устраивает, но не работает с битовыми полями.

Не работает при вызове TICK2 в SysTick при оптимизации Os, хотя при использовании во вложенных функциях, вызываемых из SysTick - работает.
Блин...
Сделаю выделенный "тикающий тип" и заведу функцию для контроля передаваемого типа.
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Dec 16 2012, 19:09
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(adnega @ Dec 16 2012, 20:52) *
Сделаю выделенный "тикающий тип" и заведу функцию для контроля передаваемого типа.

Почему перегрузку функций не использовать?
Go to the top of the page
 
+Quote Post
adnega
сообщение Dec 16 2012, 19:14
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702



Цитата(adnega @ Dec 16 2012, 22:52) *
Не работает при вызове TICK2 в SysTick при оптимизации Os, хотя при использовании во вложенных функциях, вызываемых из SysTick - работает.
Блин...
Сделаю выделенный "тикающий тип" и заведу функцию для контроля передаваемого типа.


Пока сделаю так:

Код
typedef volatile unsigned long tTIMER;

void __inline tick(tTIMER *t)
{
    tTIMER temp;
    temp = *t;
    temp += TO_TICK;
    if(temp > (*t)) *t = temp;
}

tTIMER     test_ttimer; // тестовая переменная

tick(&test_ttimer);  // вызов функции тика


Причем "тикать" строго из одного потока. Читать таймер из любого множества потоков.

Цитата(_Артём_ @ Dec 16 2012, 23:09) *
Почему перегрузку функций не использовать?

Потому что чистый C.
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Dec 16 2012, 19:21
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(adnega @ Dec 16 2012, 21:14) *
Потому что чистый C.

Зачем эта "чистота"?
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Dec 16 2012, 20:33
Сообщение #11


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Попутно еще замечание, что параметр функции const утаптывается оптимизатором лучше, и если пользоваться
Код
tTIMER __inline tick(const tTIMER tmr)
{
    tTIMER temp= tmr+TO_TICK;
    return (temp > TO_TICK)? temp:tmr;
}

tTIMER     test_ttimer; // тестовая переменная
test_ttimer = tick(test_ttimer);

может быть лучше. Вот сравните без volatile, если интересно, конечно sm.gif
Go to the top of the page
 
+Quote Post
polyname
сообщение Dec 17 2012, 06:11
Сообщение #12


Частый гость
**

Группа: Участник
Сообщений: 147
Регистрация: 18-05-12
Пользователь №: 71 915



может лучше сравнивать с разностью ?
Код
#define ADD_LIMIT(x,dx,max) x = ((x) < ((max) - (dx))) ? ((x) + (dx)) : (max)


Сообщение отредактировал polyname - Dec 17 2012, 06:12
Go to the top of the page
 
+Quote Post
andrew_b
сообщение Dec 17 2012, 06:55
Сообщение #13


Профессионал
*****

Группа: Свой
Сообщений: 1 975
Регистрация: 30-12-04
Из: Воронеж
Пользователь №: 1 757



Цитата(adnega @ Dec 16 2012, 20:37) *
Параллельно узнал, что char без указания знаковости в "gcc version 4.8.0 20121121 (experimental) (Klen's GNU package (KGP) for ARM/elf platform)" является unsigned, хотя везде указывается диапазон char от -128 до 127. В "gcc версия 4.4.3 (GCC)" под Linux char знаковый.

Где нужно читать о типах данных C/GCC и приведении типов в арифметических операциях и операциях сравнения?
Читать нужно стандарт языка Си.
Цитата
15 The three types char, signed char, and unsigned char are collectively called
the character types. The implementation shall define char to have the same range,
representation, and behavior as either signed char or unsigned char.

Иными словами, знаковость типа char зависит от реализации.
Go to the top of the page
 
+Quote Post
ARV
сообщение Dec 17 2012, 18:35
Сообщение #14


Профессионал
*****

Группа: Свой
Сообщений: 1 143
Регистрация: 30-09-08
Из: Новочеркасск
Пользователь №: 40 581



#define TICK(x) x = ((x) + TO_TICK) < (x) ? (x) : ((x) + TO_TICK)

может так?


--------------------
Я бы взял частями... но мне надо сразу.
Go to the top of the page
 
+Quote Post
ViKo
сообщение Dec 17 2012, 19:03
Сообщение #15


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(adnega @ Dec 16 2012, 19:37) *
Задача: нужно написать некоторый макрос TICK(x), который бы при каждом вызове увеличивал переменную x на константу TO_TICK, но с учетом переполнения. Т.е. в случае если добавление TO_TICK вызовет переполнение, переменную x не изменять.

А вам точно нужно это? Может, лучше - с ограничением?
#define VAR_INC(x, step, max) x = ((x + step)>max)? max : (x + step)
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th June 2025 - 17:08
Рейтинг@Mail.ru


Страница сгенерированна за 0.0149 секунд с 7
ELECTRONIX ©2004-2016