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

 
 
 
Reply to this topicStart new topic
> IAR AVR 4.10A, Обойти ограничение
Sergio66
сообщение Mar 16 2005, 13:46
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 235
Регистрация: 9-02-05
Пользователь №: 2 526



Как можно обойти ограничение Embedded C++ на арифметику с enum типом?
Компиллятор грязно ругается на сл. строчку:
current_item += i;, где current_item - enum переменная, i - int.
Go to the top of the page
 
+Quote Post
IgorKossak
сообщение Mar 16 2005, 14:54
Сообщение #2


Шаман
******

Группа: Модераторы
Сообщений: 3 064
Регистрация: 30-06-04
Из: Киев, Украина
Пользователь №: 221



Диапазон представления типа int в общем случае шире enum типа, поэтому претензии компилятора вполне обоснованы.
Обойти ограничения можно приведением типа или подавлением данного диагностического сообщения, но это не элегантный выход.
Гораздо лучше изменить программу так, чтобы стилистически, с точки зрения типов, было всё верно.
Go to the top of the page
 
+Quote Post
Sergio66
сообщение Mar 16 2005, 15:56
Сообщение #3


Местный
***

Группа: Свой
Сообщений: 235
Регистрация: 9-02-05
Пользователь №: 2 526



Цитата(Sergio66 @ Mar 16 2005, 16:46)
Как можно обойти ограничение Embedded C++ на арифметику с enum типом?
Компиллятор грязно ругается на сл. строчку:
current_item += i;, где current_item - enum переменная, i - int.
*


Ругань идет даже на выражение такого типа: current_item ++; тип current_item - enum !!!
Go to the top of the page
 
+Quote Post
dxp
сообщение Mar 17 2005, 06:34
Сообщение #4


Adept
******

Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343



Цитата(Sergio66 @ Mar 16 2005, 21:56)
Ругань идет даже на выражение такого типа: current_item ++; тип current_item - enum !!!
*

Вам же совершенно правильно объяснили, что так делать в С++ нельзя. Перечислимый тип - он только представление имеет в виде целого, а суть у него иная. И идея, и реализация в С++ логичны. В отличие от С, где с enum'ом можно делать что угодно - какое вообще смысл в этом перечислении в С, не понятно!

А в С++ объект перечислимого типа может принимать только значения своего типа. Прямое присвоение целого и арифметика запрещены. Сами посудите: вот есть у Вас

Код
enum TSlon
{
   slon    = 0,
   slonick = 3,
   mamont  = 5
} Slon;


Теперь Вы пишете: Slon = 2; Какому значению типа TSlon оно будет соответствовать? Правильно - несущетсвующему, т.е. налицо нарушение самой идеи перечислимого типа: ведь он только для того и заведен, чтобы создать и манагить некое подмножетство целых. Те, которые не описаны в нем, это невалидные значения. И компилятор при статическом контроле типов эффективно подавляет подобные ошибки.

Аналогичная ситуация и с арифметикой - результат арифметической операции может порождать значение, отсутсвующее в перечислимом типе.

Единственное, что enum связывает с преобразованиями типов и целыми - это неявное преобразование значения объекта перечислимого типа в целое.

Если уж очень хоцца присвоить объекту enum'а целое. то можно пользоваться насильным приведением типа: Slon = (TSlon)2; Но применение явного приведения типа означает, что "компилятор в этом случае умывает руки и говорит: "Надеюсь, парень, ты знаешь, что делаешь!" (с). И вообще, как сказал один лобастый дядька, явное приведение типа обычно указывает на ошибку этапа проектирования. Т.е. в правильно спроектированном коде необходимости в использовании явного преобразования типа не возникает. Исключения составляют всякие низкоуровеневые вещи вроде работы с аппаратурой и прочие "финты ушами". Для того они и оставлены в языке. Но это не есть красивый правильный подход во всех остальных случаях. Привычка постоянно использовать явные преобразования - источник собственноручно разложенных граблей.


--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
Go to the top of the page
 
+Quote Post
Sergio66
сообщение Mar 17 2005, 13:59
Сообщение #5


Местный
***

Группа: Свой
Сообщений: 235
Регистрация: 9-02-05
Пользователь №: 2 526



Цитата(dxp @ Mar 17 2005, 09:34)
Цитата(Sergio66 @ Mar 16 2005, 21:56)
Ругань идет даже на выражение такого типа: current_item ++; тип current_item - enum !!!
*


А в С++ объект перечислимого типа может принимать только значения своего типа. Прямое присвоение целого и арифметика запрещены. Сами посудите: вот есть у Вас

Код
enum TSlon
{
   slon    = 0,
   slonick = 3,
   mamont  = 5
} Slon;


Теперь Вы пишете: Slon = 2; Какому значению типа TSlon оно будет соответствовать? Правильно - несущетсвующему, т.е. налицо нарушение самой идеи перечислимого типа: ведь он только для того и заведен, чтобы создать и манагить некое подмножетство целых. Те, которые не описаны в нем, это невалидные значения. И компилятор при статическом контроле типов эффективно подавляет подобные ошибки.

*



А теперь представьте задачку - (из того же примера) нужно выбрать следующее за slon значение переменной Slon. (аналогично i++). И как?
Go to the top of the page
 
+Quote Post
IgorKossak
сообщение Mar 17 2005, 14:15
Сообщение #6


Шаман
******

Группа: Модераторы
Сообщений: 3 064
Регистрация: 30-06-04
Из: Киев, Украина
Пользователь №: 221



Цитата(Sergio66 @ Mar 17 2005, 16:59)
А теперь представьте задачку - (из того же примера) нужно выбрать следующее за slon значение переменной Slon. (аналогично i++). И как?
*

Например, так:
Код
const TSlon arr[] = {slon, slonick, mamont};
и гдето в программе ...
   TSlon *ptr = arr;
...
   char myvar = *ptr++;   // т. к. объект типа enum можно присваивать char, а не наоборот
Go to the top of the page
 
+Quote Post
Sergio66
сообщение Mar 17 2005, 14:35
Сообщение #7


Местный
***

Группа: Свой
Сообщений: 235
Регистрация: 9-02-05
Пользователь №: 2 526



Цитата(IgorKossak @ Mar 17 2005, 17:15)
Цитата(Sergio66 @ Mar 17 2005, 16:59)
А теперь представьте задачку - (из того же примера) нужно выбрать следующее за slon значение переменной Slon. (аналогично i++). И как?
*

Например, так:
Код
const TSlon arr[] = {slon, slonick, mamont};
и гдето в программе ...
   TSlon *ptr = arr;
...
   char myvar = *ptr++;   // т. к. объект типа enum можно присваивать char, а не наоборот

*



В моем случае это накладно. Я имею меню, где каждый пункт имеет идентификатор типа enum. Последовательность отображения пунктов меню задается их расположением (по порядку) в тексте программы, а последовательность переходов - порядком идентификаторов enum. В условиях жесточайшей экономии памяти создавать еще один массив констант, как в примере невозможно. Т.о. мне приходится иметь арифметику с типом enum. Раньше я работал с ICC. С ним было легко "договориться". Теперь - С++, но и ответственность... Вот и парюсь. Перевести весь код в IAR. Итак довольно много различий, а тут еще и такие формальные поводы вспучить мой мозг...
Go to the top of the page
 
+Quote Post
dxp
сообщение Mar 18 2005, 07:19
Сообщение #8


Adept
******

Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343



Цитата(Sergio66 @ Mar 17 2005, 19:59)
А теперь представьте задачку - (из того же примера) нужно выбрать следующее за slon значение переменной Slon. (аналогично i++). И как?


У Вас типичная ошибка этапа проектирования: Вы неправильно выбрали тип для реализации требуемой Вам функциональности. enum тут не подходит.

Если Вам нужно просто целое, то и используйте его. Если Вам не нравится, то целое - голое, без "обвески", то приделайте обвеску - напишите класс. Типа:

Код
class TSlon
{
public:
   TSlon() : Value(0)       { }
   TSlon(int x) : Value(x) { }
   TSlon(const TSlon& x) : Value(x) { }
   void Increase() { Value++; if(Value > MAX_VAL) Value = 0; } // wrap around
   void Decrease() { Value--; if(Value < 0) Value = MAX_VAL; } // wrap around }
   void operator ++() { Increase(); }
   void operator --() { Decrease(); }
   operator int() { return Value; }
   ... // остальной интерфейс, если он требуется

private:
   int Value;
}


Тут у вас будет максимум и там, и там. И производительность максимальная, и безопасность использования. Вообще-то, С++ для этого и придуман - чтобы сочетать скорость С с безопасностью и удобством более высокоуровевых языков.

P.S. Вообще-то, интерфейсы с меню не так пишутся. Там удобно использовать иерархию полиморфных классов и виртуальные функции. Получается удобно, быстро, безопасно и расширяемо.

P.P.S. И ничего не мешает делать так, как делали на прежнем пакете - включите С режим (не используйте ключи --ec++/--eec++) и будет вам щастье smile.gif, можете мучить этот енум как заблагорассудтся. Только уже если что, не компилятор не пеняйте. smile.gif

[FONT=Courier]


--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
Go to the top of the page
 
+Quote Post
Sergio66
сообщение Mar 18 2005, 10:16
Сообщение #9


Местный
***

Группа: Свой
Сообщений: 235
Регистрация: 9-02-05
Пользователь №: 2 526



Здесь была длинная и ненужная цитата. В следующий раз будет предупреждение
Все верно, только при разработке проекта 2 года назад был выбран компиллятор ICC. Теперь остается только облизываться на прелести С++; Переписывать 20 000 строк под С++ никакой бюджет не выдержит smile.gif)

Сообщение отредактировал IgorKossak - Mar 18 2005, 10:33
Go to the top of the page
 
+Quote Post

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

 


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


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