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

 
 
3 страниц V   1 2 3 >  
Reply to this topicStart new topic
> Интересный глюк в CodeVisionAVR
DMD
сообщение Apr 17 2008, 09:02
Сообщение #1


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

Группа: Свой
Сообщений: 120
Регистрация: 19-02-08
Пользователь №: 35 166



Обнаружил интересный глюк в CodeVision, целый день вчера просидел - думал во мне дело, оказалось, что нет.
Если мы делаем сдвиг и результирующее число выходит из размера 1 байта, то, почему-то, компилятор не преобразует его к int (хотя обязан по стандарту). То есть вот такой код работает непрявильно:
Код
unisigned char s = 243;
//...
unsigned int d = (unsigned int)(s << 4);  // d != 3888


а надо так делать, что глупо...

Код
unisigned char s = 243;
//...
unsigned int d = (unsigned int)(((unsigned int)s) << 4);  // d = 3888


Интересно, зачем это надо или это просто баг??..


--------------------
Все будет хорошо! Я проверял!
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Apr 17 2008, 09:17
Сообщение #2


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Да, выходит, это еще одно несоответствие стандарту этого компилятора.
Можно написать проще:
Код
unsigned int d = (unsigned int)s << 4;


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
prottoss
сообщение Apr 17 2008, 10:31
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(DMD @ Apr 17 2008, 16:02) *
Обнаружил интересный глюк в CodeVision, целый день вчера просидел - думал во мне дело, оказалось, что нет.
Код
unisigned char s = 243;
//...
unsigned int d = (unsigned int)(s << 4);  // d != 3888
А по моему - все правилно делает компилятор:

1. Выполняется выражение в скобках - 8-бит переменная сдвигается на четыре бита влево

2. Результат преобразуется к беззнаковому целому.



А вот так:

Код
unisigned char s = 243;
//...
unsigned int d = (unsigned int)(((unsigned int)s) << 4);  // d = 3888


1. Выполняется выражение во внутренних скобках - s преобразуется к беззнаковому целому.

2. Выполняется выражение во внешних скобках - 16-бит беззнаковое целое сдвигается на четыре бита влево

3. Результат преобразуется к беззнаковому целому



Все правильно smile.gif


--------------------
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Apr 17 2008, 11:20
Сообщение #4


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(prottoss @ Apr 17 2008, 13:31) *
А по моему - все правилно делает компилятор:
"По-вашему" - вполне вероятно. Но по стандарту должно быть иначе:
Цитата
6.3.1 Arithmetic operands
6.3.1.1 Boolean, characters, and integers

....
2 The following may be used in an expression wherever an int or unsigned int may be used:
— An object or expression with an integer type whose integer conversion rank is less than the rank of int and unsigned int.
— A bit-field of type _Bool, int, signed int,or unsigned int.
If an int can represent all values of the original type, the value is converted to an int; otherwise, it is converted to an unsigned int. These are called the integer promotions. All other types are unchanged by the integer promotions.
И раз есть отличие от стандарта, то оно должно быть явно указано в документации (например, в документации на микрочиповский C18 такое описание есть). А если в документации оно не упомянуто, то, извините, или бага или этот компилятор не может называться "компилятором языка высокого уровня С"


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
WHALE
сообщение Apr 17 2008, 12:33
Сообщение #5


Знающий
****

Группа: Свой
Сообщений: 902
Регистрация: 2-01-06
Из: Краснодар
Пользователь №: 12 768



Цитата(DMD @ Apr 17 2008, 13:02) *
Обнаружил интересный глюк в CodeVision, целый день вчера просидел - думал во мне дело, оказалось, что нет.
Если мы делаем сдвиг и результирующее число выходит из размера 1 байта, то, почему-то, компилятор не преобразует его к int (хотя обязан по стандарту). То есть вот такой код работает непрявильно:
Код
unisigned char s = 243;
//...
unsigned int d = (unsigned int)(s << 4);  // d != 3888


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

it is important to note that if the Project|Configure|C Compiler|Code Generation|Promote char to int option isn't checked or the #pragma promotechar+ isn't used, the char, respectively unsigned char, type operands are not automatically promoted to int , respectively unsigned int, as in compilers targeted for 16 or 32 bit CPUs.
This helps writing more size and speed efficient code for an 8 bit CPU like the AVR.
To prevent overflow on 8 bit addition or multiplication, casting may be required.
The compiler issues warnings in these situations.

Варнинги то хоть генерились,или они подавлены?


--------------------
"Hello, word!" - 17 errors 56 warnings
Go to the top of the page
 
+Quote Post
prottoss
сообщение Apr 18 2008, 00:42
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(Сергей Борщ @ Apr 17 2008, 18:20) *
"По-вашему" - вполне вероятно. Но по стандарту должно быть иначе:
И раз есть отличие от стандарта, то оно должно быть явно указано в документации (например, в документации на микрочиповский C18 такое описание есть). А если в документации оно не упомянуто, то, извините, или бага или этот компилятор не может называться "компилятором языка высокого уровня С"
Сорри, ошибся a14.gif


--------------------
Go to the top of the page
 
+Quote Post
Andrew O. Shadou...
сообщение Apr 18 2008, 02:01
Сообщение #7


Участник
*

Группа: Свой
Сообщений: 37
Регистрация: 13-05-07
Из: Minsk, Belarus
Пользователь №: 27 694



Цитата(Сергей Борщ @ Apr 17 2008, 14:20) *
или этот компилятор не может называться "компилятором языка высокого уровня С"

А он и так не является компилятором C. В C нет возможности писать вещи вроде PORTA.0=1, нет конструкции interrupt[wtf] и ещё много чего. Даже в C99.
Поэтому только avr-gcc.

--
WBR, Andrew
Go to the top of the page
 
+Quote Post
DMD
сообщение Apr 18 2008, 09:41
Сообщение #8


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

Группа: Свой
Сообщений: 120
Регистрация: 19-02-08
Пользователь №: 35 166



Ворнинги не генерились, что и странно. А насчет того, чтобы пользоваться опцией Project|Configure|C Compiler|Code Generation|Promote char to int - так это изврат, по-моему.


--------------------
Все будет хорошо! Я проверял!
Go to the top of the page
 
+Quote Post
ReAl
сообщение Apr 18 2008, 14:50
Сообщение #9


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

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



Цитата(DMD @ Apr 17 2008, 12:02) *
Обнаружил интересный глюк в CodeVision, целый день вчера просидел - думал во мне дело, оказалось, что нет.

Уже обсуждалось. "Выбрось каку".


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
zhevak
сообщение Dec 2 2008, 15:52
Сообщение #10


Знающий
****

Группа: Свой
Сообщений: 723
Регистрация: 29-08-05
Из: Березовский
Пользователь №: 8 065



Выбрось каку wink.gif

Прошу не пинать -- прошелся поиском по сайту и нашел сто-0-олько тем про глюконат-кодевижина, что прям ой! Вобщем, пощщу (от сл. "постить") в первый попавшийся топик по глюкам.

Сегодня приспичило меня поднять старые исходники, которые я еще писал в CodeVision в хз каком мохнатом году... Думал, закопипащщу (опять, гы-гы) текст в ИАР, подправлю где надо порты/регистры и вперед! Тема-то изъезженная вдоль и поперек -- подключение текстового LCD. Чего тут думать-то!? Ан, нет! Старые грабли с новыми ручкам...

Короче, IAR обнаружил ошибку на выходе из функции. Стыдно признаться, но это так, -- моя невнимательность. Но меня другое плющит -- Codevision эту ошибку в упор не видит. Пф-ф!

Вот код функции (слегка урезанный):
Код
//
//  Перевод кодировки Win-1251 в LDC-кодировку
//
BYTE _Translate(BYTE data)
{
  switch (data)
  {
  case 'Ё':
    return 0xA2;
  case 'ё':
...
  case '№':
    return 0xCC;
  case '\\':
    return 0xFF;
  }

  if (data >= 0xC0)
    return rus[data - 0xC0];
}


Для молодых поэтов поясняю -- собака порылась в последнем операторе if.

Вопрос: что будет, если data будет меньше 0xC0? Какой код вернет функция? Правльный выход из функции должен быть, разумеется, такой:
Код
...
  if (data >= 0xC0)
    return rus[data - 0xC0];
  else
    return data;
}


(Может кому пригодится. Хех!)


--------------------
Хочешь рассмешить Бога -- расскажи ему о своих планах!
Go to the top of the page
 
+Quote Post
defunct
сообщение Dec 3 2008, 00:15
Сообщение #11


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(Сергей Борщ @ Apr 17 2008, 11:17) *
Можно написать проще:
Код
unsigned int d = (unsigned int)s << 4;

Можно написать еще проще
Код
unsigned int d = s << 4;

зачем делать приведение типа в правой части, если в левой части и так unsigned int.

к тому же
Цитата
Все операнды типа unsigned char или unsigned short преобразуются в тип unsigned int.



Цитата(zhevak @ Dec 2 2008, 17:52) *
разумеется, такой:

Неочевидно, потому что ваш пример вообще неоткомилируется, неизвестно что такое rus smile.gif

Очень странно как вы использовали этот код и не наткнулись на проблему раньше, ведь 3/4 символов, в т.ч. и цифры, были недоступными!

По теме CV согласен - фтопку этот недоинструмент.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Dec 3 2008, 01:58
Сообщение #12


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(defunct @ Dec 3 2008, 02:15) *
Можно написать еще проще
Код
unsigned int d = s << 4;

зачем делать приведение типа в правой части, если в левой части и так unsigned int.
Если опустить integer promotion rules, которые CV не соблюдает, то в остальном в этом выражении он действует по стандарту: сначала вычисляется правая часть, потом ее результат приводится к левой части. То, что вы написали другими словами можно представить примерно так:
Цитата
Код
unsigned int s = 0x1234;
unsigned long d = s << 4;

зачем делать приведение типа в правой части, если в левой части и так unsigned long.


Цитата(zhevak @ Dec 2 2008, 17:52) *
Но меня другое плющит -- Codevision эту ошибку в упор не видит. Пф-ф!
gcc без -Wall тоже пропускает такое. В свое время тоже был удивлен, когда старые проекты, писаные в оболочке Dev-C++ стал собирать со своим рукописным makefile. Тоже решил тогда для себя "нафиг оболочку, теперь makefiles только руками".
А с -Wall gcc выдает не ошибку, а предупреждение.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Nick_Shl
сообщение Dec 3 2008, 06:15
Сообщение #13


Участник
*

Группа: Участник
Сообщений: 55
Регистрация: 17-04-08
Пользователь №: 36 850



Цитата(zhevak @ Dec 2 2008, 17:52) *
Вопрос: что будет, если data будет меньше 0xC0? Какой код вернет функция?
Все зависит от того, что вы выкинули заменив точечками в switch'e возможно за этот if управление даже не выйдет.
Кстати, насколько я припоминаю, у КодеВижена есть настройка какие варнинги выводить, а какие нет. Надо там глянуть не отключены ли.
Go to the top of the page
 
+Quote Post
delamoure
сообщение Dec 3 2008, 11:48
Сообщение #14


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

Группа: Свой
Сообщений: 176
Регистрация: 2-04-08
Из: Днепропетровск
Пользователь №: 36 406



Цитата(ReAl @ Apr 18 2008, 16:50) *
Уже обсуждалось. "Выбрось каку".


Кака, конечно.
Но если бы в IAR C было также просто вставлять ассемблерный код в текс программы как это сделано в CvAVR... crying.gif


--------------------
Ребята, как же это вы без гравицапы пепелац выкатываете из гаража? Это непорядок. ©
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Dec 3 2008, 13:35
Сообщение #15


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(delamoure @ Dec 3 2008, 13:48) *
Но если бы в IAR C было также просто вставлять ассемблерный код в текс программы как это сделано в CvAVR... crying.gif
Тогда вам в gcc. Такого шикарного инлайн-асма в других компиляторах не встречалось. Вставленный код не мешает оптимизатору, компилятор сам решает, в каких регистрах удобнее передать параметры в ваш ассемблерный кусок... Конфетка! Не знаю как CV, но ИАР встретив в функции инлайн-асм складывает крылья и выключает оптимизатор (где-то в описании было).


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post

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

 


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


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