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

 
 
 
Reply to this topicStart new topic
> Кто подскажет - это глюк Keil ?
IF_P
сообщение Dec 22 2008, 19:58
Сообщение #1


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

Группа: Участник
Сообщений: 136
Регистрация: 2-01-06
Пользователь №: 12 772



Перешел на Keil-51. В Proview32 работало нормально а в Keil глючит. Это глюк или так должно быть?
При суммировании 99+99+99+99+99+99+99+99 получем ==03 (видимо старший байт результата - 0x0318)

PS: глобальные переменные
xdata unsigned int W_max, W_mid;

Сообщение отредактировал IF_P - Dec 22 2008, 20:22
Прикрепленные файлы
Прикрепленный файл  test.rar ( 130.44 килобайт ) Кол-во скачиваний: 26
Прикрепленный файл  test.rar ( 130.44 килобайт ) Кол-во скачиваний: 18
 
Go to the top of the page
 
+Quote Post
rezident
сообщение Dec 22 2008, 21:34
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Либо я не понял сути проблемы, либо вы не понимаете сути типизации и арифметических действий в Си. laughing.gif
Каждое из значений (число 99) слагаемых конечной суммы в вашем выражении можно представить типом char, но сумму из восьми чисел (99*8=792=0x318) уже нельзя представить типом char, т.к. оно превышает разрядность этого типа (0<=unsigned char<=255=0xFF) и происходит переполнение переменной. По этой причине сумма усекается до числа представимого с помощью типа char (0x18=24). Ну а деление полученного (усеченного) числа на 8 и дает искомое число 3 (24/8=3).
В общем рекомендую внимательнее изучить стандарт Си.
Go to the top of the page
 
+Quote Post
IF_P
сообщение Dec 22 2008, 22:30
Сообщение #3


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

Группа: Участник
Сообщений: 136
Регистрация: 2-01-06
Пользователь №: 12 772



Цитата(rezident @ Dec 22 2008, 23:34) *
Либо я не понял сути проблемы, либо вы не понимаете сути типизации и арифметических действий в Си. laughing.gif
Каждое из значений (число 99) слагаемых конечной суммы в вашем выражении можно представить типом char, но сумму из восьми чисел (99*8=792=0x318) уже нельзя представить типом char, т.к. оно превышает разрядность этого типа (0<=unsigned char<=255=0xFF) и происходит переполнение переменной. По этой причине сумма усекается до числа представимого с помощью типа char (0x18=24). Ну а деление полученного (усеченного) числа на 8 и дает искомое число 3 (24/8=3).
В общем рекомендую внимательнее изучить стандарт Си.


Я понимаю, что такое тип переменной и как он представляется в Си. Видимо я не совсем понятно объяснил суть проблемы. Суммируются 8 чисел, каждое меньше 100. Результат объявлен как unsigned int. Следовательно, результат помещается в переменной.
Keil суммирует числа так как они написаны в программе: к а прибавляется b (но в формате char). Потом к результату прибавляется c и т.д. Но все в формате char. Получается переполнение.
В отличие от этого Franklin все делает правильно. Он суммирует числа через промежуточные р-ры (R6,R7) с учетом переноса.
Я для сравнения привел ассемблерную мнемонику обеих компиляторов, где и можно все это увидеть.

Что касаетсят программирования на Си, то эта программа нормально работает более двух лет, а вышеуказанная проблема возникла при переходе на Keil.

Я в комментарии указал каким образом Keil работает нормально (все переменные описаны как unsigned int), Но при этом увеличивается память. А ведь Franklin прекрасно все понимает с переменными char. Хотелось бы знать как поступать в будущем.
Go to the top of the page
 
+Quote Post
rezident
сообщение Dec 22 2008, 22:41
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(IF_P @ Dec 23 2008, 03:30) *
Хотелось бы знать как поступать в будущем.
Поступать нужно так, как предписывает стандарт языка Си. Все более современные компиляторы стараются следовать этому стандарту как можно точнее. Причем вам совсем не обязательно все переменные передавать в функцию как unsigned int. Можно всего лишь одну из переменных типа unsigned char в конечном выражении явно привести к типу unsigned int. И тогда все остальные переменные при вычислении суммы будут автоматически приведены к более старшему типу в соответствии со стандартом Си.

Код
W_mid=((unisgned int)a+b+c+d+e+f+g+h)/n_W;
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Dec 22 2008, 22:53
Сообщение #5


Гуру
******

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



Цитата(rezident @ Dec 23 2008, 00:41) *
И тогда все остальные переменные при вычислении суммы будут автоматически приведены к более старшему типу в соответствии со стандартом Си.
В соответствии со стандартом они и так должны быть приведены к int неявно (integer promotion rules). Микрочиповский MPLAB-C30 по умолчанию не делает этого (описано в документации), но имеет ключик "делать как положено по стандарту". Возможно и Кейл поступает также? Во всяком случае поискать в документации слово "promotion" и внимательно просмотреть описание ключей компилятора не помешает.


--------------------
На любой вопрос даю любой ответ
"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
rezident
сообщение Dec 22 2008, 23:00
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(Сергей Борщ @ Dec 23 2008, 03:53) *
Возможно и Кейл поступает также? Во всяком случае поискать в документации слово "promotion" и внимательно просмотреть описание ключей компилятора не помешает.
Действительно в Keil есть такая опция!
http://www.keil.com/support/docs/1494.htm
http://www.keil.com/support/man/docs/c51/c51_intpromote.htm
Go to the top of the page
 
+Quote Post
IF_P
сообщение Dec 23 2008, 13:51
Сообщение #7


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

Группа: Участник
Сообщений: 136
Регистрация: 2-01-06
Пользователь №: 12 772



Цитата(rezident @ Dec 23 2008, 01:00) *

В документации указано, что по умолчанию INTPROMOTE. Попробовал объявить явно:

#pragma intpromote
или
#pragma nointpromote

Ничего не изменилось. Но это описано касательно условных операторов. Возможно, где-то еще есть "ключик". Может кто знает? У меня мVision2V2.36, C51-V7.04.

А вот что касается рекомендации rezident по приведения типов, то это работает.

W_mid=((unisgned int)a+b+c+d+e+f+g+h)/n_W;
Go to the top of the page
 
+Quote Post
Палыч
сообщение Dec 23 2008, 13:59
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(IF_P @ Dec 23 2008, 16:51) *
В документации указано, что по умолчанию INTPROMOTE. Попробовал объявить явно:
#pragma intpromote
или
#pragma nointpromote
Ничего не изменилось.
А, может - проще: галочку поставить?
Menu -> Project -> Options for Target -> C51 -> Enable ANSI integer promotion rules
Go to the top of the page
 
+Quote Post
IF_P
сообщение Dec 23 2008, 16:23
Сообщение #9


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

Группа: Участник
Сообщений: 136
Регистрация: 2-01-06
Пользователь №: 12 772



Цитата(Палыч @ Dec 23 2008, 15:59) *
А, может - проще: галочку поставить?
Menu -> Project -> Options for Target -> C51 -> Enable ANSI integer promotion rules

Галочка стоит (настройка по умолчанию)
Go to the top of the page
 
+Quote Post
Палыч
сообщение Dec 23 2008, 17:13
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(IF_P @ Dec 23 2008, 19:23) *
Галочка стоит (настройка по умолчанию)
Тогда - все char должны приводиться к int в соответствии со стандартом! Может быть, Вы нечаяно убрали эту галку именно для конкретного файла? Посмотрите - нет ли трёх жирных точек у значка файла в окне Project Workspace? Если - есть, то для этого файла также поставьте галочку.
Go to the top of the page
 
+Quote Post
IF_P
сообщение Dec 23 2008, 17:53
Сообщение #11


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

Группа: Участник
Сообщений: 136
Регистрация: 2-01-06
Пользователь №: 12 772



Цитата(Палыч @ Dec 23 2008, 19:13) *
Тогда - все char должны приводиться к int в соответствии со стандартом! Может быть, Вы нечаяно убрали эту галку именно для конкретного файла? Посмотрите - нет ли трёх жирных точек у значка файла в окне Project Workspace? Если - есть, то для этого файла также поставьте галочку.

И три точки есть и галочка есть.
Прикрепленные файлы
Прикрепленный файл  Flag.rar ( 52.84 килобайт ) Кол-во скачиваний: 37
 
Go to the top of the page
 
+Quote Post
rezident
сообщение Dec 23 2008, 18:29
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



IF_P, в Windows есть растровый графический редактор Paint. Из него можно сохранять изображения в форматах JPG и GIF. Пользуйтесь, пожалуйста им для сохранения скриншотов, а не вставкой картинки в Word. Во-первых, неудобно: картинка в текстовом документа, да еще и зархивированная 07.gif , во-вторых, весьма мелкое изображение получается. Создание изображение в Paint точно такое же как и в Word. PrintScreen или CTRL+PrintScreen для снятия скриншота, а потом в Paint CTRL+V и CTRL+S для сохранения.
Go to the top of the page
 
+Quote Post
IF_P
сообщение Dec 23 2008, 18:42
Сообщение #13


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

Группа: Участник
Сообщений: 136
Регистрация: 2-01-06
Пользователь №: 12 772



Цитата(rezident @ Dec 23 2008, 20:29) *
IF_P, в Windows есть растровый графический редактор Paint. Из него можно сохранять изображения в форматах JPG и GIF. Пользуйтесь, пожалуйста им для сохранения скриншотов, а не вставкой картинки в Word. Во-первых, неудобно: картинка в текстовом документа, да еще и зархивированная 07.gif , во-вторых, весьма мелкое изображение получается. Создание изображение в Paint точно такое же как и в Word. PrintScreen или CTRL+PrintScreen для снятия скриншота, а потом в Paint CTRL+V и CTRL+S для сохранения.

Спасибо за замечание. Учту
Go to the top of the page
 
+Quote Post

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

 


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


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