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

 
 
> Макрос инкремента с насыщением.
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
 
Start new topic
Ответов
ReAl
сообщение Dec 18 2012, 13:02
Сообщение #2


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(adnega @ Dec 16 2012, 18:37) *
не помогает, в случае знакового x и беззнакового TO_TICK. Видимо, (x + TO_TICK) считается беззнаковым и сравнивается с беззнаковым x.
Конечно, если TO_TICK явно беззнаковое, то в (x + TO_TICK) сначала будет приведение x к беззнаковому.
А зачем TO_TICK беззнаковое? Оно же явно должно влазить по диапазону в знаковые числа, а при (unsignedX + signedTICK) уже тик приведётся к беззнаковому и будет все нормально.
Хотя с битовыми полями и прочими заужениями до байтов все равно будет плохо, так как в + сначала обе стороны приведутся к int и для uint8_t всё равно всегда ((255+1) > 255) истинно и прибавление тика не остановится.

Кстати, с typeof можно и проще
Код
#define TICK(x) do { if ( (typeof(x))(x+TO_TICK) > x ) x += TO_TICK;}while(0)

но с битовыми полями так же не будет работать. Хотя я в таких местах ниже байта не опускаюсь, битовые поля - счётчики немного экономят ОЗУ, но раздувают код (Cortex-M3-шные команді работы с битовыми полями штука хорошая, но не везде есть).

И лучше уж C++ шаблонную функцию, чем такой макрос. Не вижу препятствий работать в процедурном стиле даже без простейших классов, но с такого рода шаблонами. А для кого есть gcc, для того есть и g++.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
adnega
сообщение Dec 20 2012, 10:40
Сообщение #3


Гуру
******

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



Цитата(ReAl @ Dec 18 2012, 17:02) *
Конечно, если TO_TICK явно беззнаковое, то в (x + TO_TICK) сначала будет приведение x к беззнаковому.
А зачем TO_TICK беззнаковое? Оно же явно должно влазить по диапазону в знаковые числа, а при (unsignedX + signedTICK) уже тик приведётся к беззнаковому и будет все нормально.

Я-то боюсь, что "умный" оптимизатор вообще вправе выкинуть финт: если к некоторому числу прибавить положительную константу, то результат (чисто в математическом смысле) будет БОЛЬШЕ исходного числа - поэтому условие всегда истинное. А если программисту нужна такая "платформенная вещь" как "переполнение", то либо врукопашную оптимизируй, либо научись грамотно указать оптимизатору свои намеренья.

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

Для битовых полей написать специальный макрос/функцию для выполнения этой конкретной задачи.

Вообще, это скорее проблема программиста (моя), а не инструмента: хочется чтобы программа сама себя писала, но для решения данной проблемы есть ДРУГИЕ инструменты, которыми и нужно пользоваться.
Go to the top of the page
 
+Quote Post
scifi
сообщение Dec 20 2012, 11:09
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(adnega @ Dec 20 2012, 14:40) *
Я-то боюсь, что "умный" оптимизатор вообще вправе выкинуть финт: если к некоторому числу прибавить положительную константу, то результат (чисто в математическом смысле) будет БОЛЬШЕ исходного числа - поэтому условие всегда истинное.

Зря боитесь, не будет такого. Компилятор всё делает по стандарту языка Си (с точностью до глюков компилятора, но мы же не о них сейчас говорим). В стандарте четко прописана семантика переполнения целочисленной переменной.

Цитата(adnega @ Dec 20 2012, 14:40) *
Вообще, это скорее проблема программиста (моя), а не инструмента: хочется чтобы программа сама себя писала, но для решения данной проблемы есть ДРУГИЕ инструменты, которыми и нужно пользоваться.

Я с самого начала это хотел сказать. Мне кажется, необходимость насыщения должна возникать редко, поэтому и макрос тут ни к чему.
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- adnega   Макрос инкремента с насыщением.   Dec 16 2012, 16:37
- - _Pasha   Код#define TICK(x) do{ unsigned char a = x...   Dec 16 2012, 16:59
|- - adnega   Цитата(_Pasha @ Dec 16 2012, 20:59) и воо...   Dec 16 2012, 17:46
|- - _Pasha   Цитата(adnega @ Dec 16 2012, 20:46) Чтобы...   Dec 16 2012, 18:26
|- - adnega   Цитата(_Pasha @ Dec 16 2012, 22:26) Во...   Dec 16 2012, 18:29
|- - _Pasha   Цитата(adnega @ Dec 16 2012, 21:29) А то...   Dec 16 2012, 18:40
- - adnega   Цитата(adnega @ Dec 16 2012, 20:37) Вариа...   Dec 16 2012, 18:52
|- - _Артём_   Цитата(adnega @ Dec 16 2012, 20:52) Сдела...   Dec 16 2012, 19:09
|- - adnega   Цитата(adnega @ Dec 16 2012, 22:52) Не ра...   Dec 16 2012, 19:14
|- - _Артём_   Цитата(adnega @ Dec 16 2012, 21:14) Потом...   Dec 16 2012, 19:21
- - _Pasha   Попутно еще замечание, что параметр функции const ...   Dec 16 2012, 20:33
- - polyname   может лучше сравнивать с разностью ? Код#define AD...   Dec 17 2012, 06:11
- - andrew_b   Цитата(adnega @ Dec 16 2012, 20:37) Парал...   Dec 17 2012, 06:55
- - ARV   #define TICK(x) x = ((x) + TO_TICK) < (x) ? (x)...   Dec 17 2012, 18:35
- - ViKo   Цитата(adnega @ Dec 16 2012, 19:37) Задач...   Dec 17 2012, 19:03
|- - adnega   Цитата(ViKo @ Dec 17 2012, 23:03) А вам т...   Dec 17 2012, 19:32
- - _Pasha   Мне интересно другое. А насыщение в виде равенства...   Dec 20 2012, 12:00


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

 


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


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