|
Интересный глюк в CodeVisionAVR |
|
|
|
Apr 17 2008, 09:02
|

Частый гость
 
Группа: Свой
Сообщений: 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 Интересно, зачем это надо или это просто баг??..
--------------------
Все будет хорошо! Я проверял!
|
|
|
|
|
Apr 17 2008, 09:17
|

Гуру
     
Группа: Модераторы
Сообщений: 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)
|
|
|
|
|
Apr 17 2008, 10:31
|

Гуру
     
Группа: Свой
Сообщений: 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. Результат преобразуется к беззнаковому целому Все правильно
--------------------
|
|
|
|
|
Apr 17 2008, 11:20
|

Гуру
     
Группа: Модераторы
Сообщений: 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)
|
|
|
|
|
Apr 17 2008, 12:33
|

Знающий
   
Группа: Свой
Сообщений: 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
|
|
|
|
|
Apr 18 2008, 02:01
|
Участник

Группа: Свой
Сообщений: 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
|
|
|
|
|
Dec 2 2008, 15:52
|

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

|
Выбрось каку  Прошу не пинать -- прошелся поиском по сайту и нашел сто-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; } (Может кому пригодится. Хех!)
--------------------
Хочешь рассмешить Бога -- расскажи ему о своих планах!
|
|
|
|
|
Dec 3 2008, 00:15
|

кекс
     
Группа: Свой
Сообщений: 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  Очень странно как вы использовали этот код и не наткнулись на проблему раньше, ведь 3/4 символов, в т.ч. и цифры, были недоступными! По теме CV согласен - фтопку этот недоинструмент.
|
|
|
|
|
Dec 3 2008, 01:58
|

Гуру
     
Группа: Модераторы
Сообщений: 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)
|
|
|
|
|
Dec 3 2008, 06:15
|
Участник

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

|
Цитата(zhevak @ Dec 2 2008, 17:52)  Вопрос: что будет, если data будет меньше 0xC0? Какой код вернет функция? Все зависит от того, что вы выкинули заменив точечками в switch'e возможно за этот if управление даже не выйдет. Кстати, насколько я припоминаю, у КодеВижена есть настройка какие варнинги выводить, а какие нет. Надо там глянуть не отключены ли.
|
|
|
|
|
Dec 3 2008, 11:48
|

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

|
Цитата(ReAl @ Apr 18 2008, 16:50)  Уже обсуждалось. "Выбрось каку". Кака, конечно. Но если бы в IAR C было также просто вставлять ассемблерный код в текс программы как это сделано в CvAVR...
--------------------
Ребята, как же это вы без гравицапы пепелац выкатываете из гаража? Это непорядок. ©
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|