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

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Прошу совета по индексам массивов
king2
сообщение Nov 6 2006, 03:02
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 255
Регистрация: 17-08-06
Из: Москва
Пользователь №: 19 646



Есть такой вот код:

Код
    171                usb_buffer[usb_txtail++]=0x05;
   \   00000094   9160....           LDS     R22, usb_txtail
   \   00000098   2F56               MOV     R21, R22
   \   0000009A   9553               INC     R21
   \   0000009C   9350....           STS     usb_txtail, R21
   \   000000A0   E055               LDI     R21, 5
   \   000000A2   E070               LDI     R23, 0
   \   000000A4   01FB               MOVW    R31:R30, R23:R22
   \   000000A6   ....               SUBI    R30, LOW((-(usb_buffer) & 0xFFFF))
   \   000000A8   ....               SBCI    R31, (-(usb_buffer) & 0xFFFF) >> 8
   \   000000AA   8350               ST      Z, R21


Изначально предполагалось, что так как usb_txtail unsigned char, то оно досчитает до 255 и начнет снова с нуля без всяких танцев с бубнами. А фиг...

Если после этого вставить строчку:
Код
if (usb_txtail == 255) usb_txtail = 0;

то все работает на ура. Если этой строчки нет - досчитав до 255, начинается какая-то свистопляска, оно выводит содержимое буфера еще раз...

Есть какие-нить идеи на эту тему? smile.gif
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Nov 6 2006, 08:57
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(king2 @ Nov 6 2006, 06:02) *
Если после этого вставить строчку:
Код
if (usb_txtail == 255) usb_txtail = 0;

Если добавить эту строку, то элемент с индексом 255 никогда не будет записан.
Осталось разобраться, почему эта запись все ломает. Может быть, буфер случайно объявлен как usb_buffer[255]?
Go to the top of the page
 
+Quote Post
_Bill
сообщение Nov 6 2006, 09:38
Сообщение #3


Местный
***

Группа: Участник
Сообщений: 416
Регистрация: 18-04-06
Из: Челябинск
Пользователь №: 16 219



Цитата(king2 @ Nov 6 2006, 06:02) *
Есть такой вот код:

Изначально предполагалось, что так как usb_txtail unsigned char, то оно досчитает до 255 и начнет снова с нуля без всяких танцев с бубнами. А фиг...

Если после этого вставить строчку:
Код
if (usb_txtail == 255) usb_txtail = 0;

то все работает на ура. Если этой строчки нет - досчитав до 255, начинается какая-то свистопляска, оно выводит содержимое буфера еще раз...

Есть какие-нить идеи на эту тему? smile.gif

Есть два варианта:
1. usb_buffer[(unsigned char)(usb_txtail++)]=0x05;
2. usb_buffer[usb_txtail++ % 255]=0x05;
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Nov 6 2006, 10:18
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата
Есть два варианта:

А Вас не смущает то, что результат работы этих двух вариантов будет разным?

Проблема не в типе char, с которым компилятор обошелся совершенно корректно, а, скорее всего, в размере буфера.
Go to the top of the page
 
+Quote Post
rezident
сообщение Nov 6 2006, 10:37
Сообщение #5


Гуру
******

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



А тип самого буфера наверное unsigned int? А попробуйте-ка разбить код на две операции
Код
usb_buffer[usb_txtail]=0x05;
usb_txtail++;

и сообщите что получается.
Go to the top of the page
 
+Quote Post
prottoss
сообщение Nov 6 2006, 12:00
Сообщение #6


Гуру
******

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



Скомпилил вот такой код:
Код
UCHAR bfr[300];
UCHAR indx;

void main(void)
{
   indx = 0;
   for(UINT i = 0; i < 300; i++)
       bfr[indx++] = 5;
}
Так вот, после значения 255 переменная indx принимает значение НОЛЬ. Ищите косяки в программе. НИКОГДА, если переменная объявлена как CHAR, компилятор не переделает ее в INT, LONG, LONLONG или FLOAT, если вы прямо ему об этом не укажите...


--------------------
Go to the top of the page
 
+Quote Post
rezident
сообщение Nov 6 2006, 12:57
Сообщение #7


Гуру
******

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



Цитата(prottoss @ Nov 6 2006, 17:00) *
НИКОГДА, если переменная объявлена как CHAR, компилятор не переделает ее в INT, LONG, LONLONG или FLOAT, если вы прямо ему об этом не укажите...

"Никогда не говори ''никогда''" smile.gif А про приведение типов в языке СИ вы знаете? И что бывает в случае арифметических операций с числами разной разрядности, надеюсь тоже в курсе?
Цитата из K&R (переводная, из библиотеки Мошкова). Глава 1.6. Массивы
Цитата
По определению перед проведением арифметических опера-
ций, вовлекающих переменные типа CHAR и INT, все они преоб-
разуются к типу INT, TAK что в арифметических выражениях пе-
ременные типа CHAR по существу идентичны переменным типа
INT.

Еще раз предлагаю инкремент индекса вынести как отдельную операцию. У меня нет IAR for AVR, чтобы проверить получившийся результат на ассемблере.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Nov 6 2006, 13:11
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(rezident @ Nov 6 2006, 15:57) *
Еще раз предлагаю инкремент индекса вынести как отдельную операцию. У меня нет IAR for AVR, чтобы проверить получившийся результат на ассемблере.

Код приведен в первом посте.
Go to the top of the page
 
+Quote Post
rezident
сообщение Nov 6 2006, 13:51
Сообщение #9


Гуру
******

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



Вот еще в Википедии отыскал существенное (по-моему) замечание/комментарий, подходящее как раз для данного случая.
Цитата
Note that for addition and subtraction of integers and pointers, the value of the pointer is not adjusted by the integer amount, but is adjusted by the amount multiplied by the size (in bytes) of the type to which the pointer refers. One pointer may also be subtracted from another, provided they point to elements of the same array (or the position just beyond the end of the array). If you have a pointer that points to an element of an array, the index of the element is the result when the array name is subtracted from the pointer. Here's an example.

Раздел 1.4 Pointers and Arrays.
Go to the top of the page
 
+Quote Post
IgorKossak
сообщение Nov 6 2006, 14:50
Сообщение #10


Шаман
******

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



Цитата(king2 @ Nov 6 2006, 05:02) *
А фиг...

Что под этим подразумевается? В отладчике смотрели?
Ведь судя по приведенному коду всё должно быть нормально.
Или это в результате вставки того пресловутого условия?

Приведите сгенерированный код с условием и без него.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Nov 6 2006, 14:56
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(rezident @ Nov 6 2006, 16:51) *
Вот еще в Википедии отыскал существенное (по-моему) замечание/комментарий, подходящее как раз для данного случая.

А по-моему, все Ваши замечания ни разу не подходят к рассматриваемому случаю angry.gif
Go to the top of the page
 
+Quote Post
rezident
сообщение Nov 6 2006, 15:02
Сообщение #12


Гуру
******

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



Цитата(aaarrr @ Nov 6 2006, 19:56) *
Цитата(rezident @ Nov 6 2006, 16:51) *

Вот еще в Википедии отыскал существенное (по-моему) замечание/комментарий, подходящее как раз для данного случая.

А по-моему, все Ваши замечания ни разу не подходят к рассматриваемому случаю angry.gif

ОК smile.gif Если резюмировать, то мои намеки были на то, что хорошим тоном является явная проверка на выход за границы массива. Вместо того, чтобы надеяться на "благоразумность" компилятора и размерность переменных им же определенных.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Nov 6 2006, 15:20
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(rezident @ Nov 6 2006, 18:02) *
ОК smile.gif Если резюмировать, то мои намеки были на то, что хорошим тоном является явная проверка на выход за границы массива. Вместо того, чтобы надеяться на "благоразумность" компилятора и размерность переменных им же определенных.

Полностью согласен. Впрочем, автор топика в результате получил от компилятора в точности то, о чем просил smile.gif
Go to the top of the page
 
+Quote Post
prottoss
сообщение Nov 6 2006, 16:27
Сообщение #14


Гуру
******

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



Цитата(rezident @ Nov 6 2006, 19:57) *
Цитата(prottoss @ Nov 6 2006, 17:00) *

НИКОГДА, если переменная объявлена как CHAR, компилятор не переделает ее в INT, LONG, LONLONG или FLOAT, если вы прямо ему об этом не укажите...

"Никогда не говори ''никогда''" smile.gif А про приведение типов в языке СИ вы знаете? И что бывает в случае арифметических операций с числами разной разрядности, надеюсь тоже в курсе?
Вы читайте, не то что выделенно большими буквами, а все предложение)

Когда мы приводим один тип к другому, мы УКАЗЫВАЕМ компилятору про тип, и, соответсвенно, разрядность переменой, тип которой мы приводим. Когда мы выполняем арифметические операции над числами разной разрядности, мы то же, неявно УКАЗЫВАЕМ компилятору на разрядность операции...

А если компилятор начнет предполагать, что после инкремента какой то переменной может произойти переполнение разрядной сетки, то все переменные, в конечном итоге, у него превратятся в LONGLONGLONGLONGLONG.....................

Для того, что бы проверить код, не обязательно иметь ИАР Си, возьмите от Борланда или Мелкософта...



Цитата(rezident @ Nov 6 2006, 19:57) *
Цитата из K&R (переводная, из библиотеки Мошкова). Глава 1.6. Массивы
Цитата
По определению перед проведением арифметических опера-
ций, вовлекающих переменные типа CHAR и INT, все они преоб-
разуются к типу INT, TAK что в арифметических выражениях пе-
ременные типа CHAR по существу идентичны переменным типа
INT.

Еще раз предлагаю инкремент индекса вынести как отдельную операцию. У меня нет IAR for AVR, чтобы проверить получившийся результат на ассемблере.
К сожалению, не читал данное произведение...

И хотя инкремент индекса, в приципе тоже арифметическая операция, ИМХО никогда любой нормальный компилятор не преобразует индекс при инкременте в переменную бОльшей разрядности... Может быть только, если этот компилятор написан Вами)


--------------------
Go to the top of the page
 
+Quote Post
_Sam_
сообщение Nov 8 2006, 08:06
Сообщение #15


Местный
***

Группа: Свой
Сообщений: 278
Регистрация: 18-01-05
Из: Санкт-Петербург
Пользователь №: 2 031



Я вообще не понял в чём проблема!

Цитата
если после этого поставить строчку if (usb_txtail == 255) usb_txtail = 0;

Получится
Код
usb_buffer[usb_txtail++]=0x05;
if (usb_txtail == 255) usb_txtail = 0;

судя по асм. листингу usb_txtail однобайтовая переменная, а значит добавленная строка вообще не влияет на результат, либо её добавляют не после "этого", а перед "этим"!

Ну да ладно читаем дальше.
Цитата
начинается какая-то свистопляска, оно выводит содержимое буфера еще раз...

А "оно" и должно выводить ещё раз! Индекс то обнулился! biggrin.gif


Цитата
И хотя инкремент индекса, в приципе тоже арифметическая операция

Было сказано про арифметические операции в которых участвуют переменные разных типовwink.gif
Go to the top of the page
 
+Quote Post

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

 


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


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