|
Прошу совета по индексам массивов |
|
|
|
Nov 6 2006, 03:02
|
Местный
  
Группа: Свой
Сообщений: 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, начинается какая-то свистопляска, оно выводит содержимое буфера еще раз... Есть какие-нить идеи на эту тему?
|
|
|
|
|
Nov 6 2006, 08:57
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(king2 @ Nov 6 2006, 06:02)  Если после этого вставить строчку: Код if (usb_txtail == 255) usb_txtail = 0; Если добавить эту строку, то элемент с индексом 255 никогда не будет записан. Осталось разобраться, почему эта запись все ломает. Может быть, буфер случайно объявлен как usb_buffer[255]?
|
|
|
|
|
Nov 6 2006, 09:38
|
Местный
  
Группа: Участник
Сообщений: 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, начинается какая-то свистопляска, оно выводит содержимое буфера еще раз... Есть какие-нить идеи на эту тему?  Есть два варианта: 1. usb_buffer[(unsigned char)(usb_txtail++)]=0x05; 2. usb_buffer[usb_txtail++ % 255]=0x05;
|
|
|
|
|
Nov 6 2006, 12:57
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(prottoss @ Nov 6 2006, 17:00)  НИКОГДА, если переменная объявлена как CHAR, компилятор не переделает ее в INT, LONG, LONLONG или FLOAT, если вы прямо ему об этом не укажите... "Никогда не говори ''никогда''"  А про приведение типов в языке СИ вы знаете? И что бывает в случае арифметических операций с числами разной разрядности, надеюсь тоже в курсе? Цитата из K&R (переводная, из библиотеки Мошкова). Глава 1.6. МассивыЦитата По определению перед проведением арифметических опера- ций, вовлекающих переменные типа CHAR и INT, все они преоб- разуются к типу INT, TAK что в арифметических выражениях пе- ременные типа CHAR по существу идентичны переменным типа INT. Еще раз предлагаю инкремент индекса вынести как отдельную операцию. У меня нет IAR for AVR, чтобы проверить получившийся результат на ассемблере.
|
|
|
|
|
Nov 6 2006, 13:51
|
Гуру
     
Группа: Свой
Сообщений: 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.
|
|
|
|
|
Nov 6 2006, 14:50
|

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

|
Цитата(king2 @ Nov 6 2006, 05:02)  А фиг... Что под этим подразумевается? В отладчике смотрели? Ведь судя по приведенному коду всё должно быть нормально. Или это в результате вставки того пресловутого условия? Приведите сгенерированный код с условием и без него.
|
|
|
|
|
Nov 6 2006, 16:27
|

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

|
Цитата(rezident @ Nov 6 2006, 19:57)  Цитата(prottoss @ Nov 6 2006, 17:00)  НИКОГДА, если переменная объявлена как CHAR, компилятор не переделает ее в INT, LONG, LONLONG или FLOAT, если вы прямо ему об этом не укажите...
"Никогда не говори ''никогда''"  А про приведение типов в языке СИ вы знаете? И что бывает в случае арифметических операций с числами разной разрядности, надеюсь тоже в курсе? Вы читайте, не то что выделенно большими буквами, а все предложение) Когда мы приводим один тип к другому, мы УКАЗЫВАЕМ компилятору про тип, и, соответсвенно, разрядность переменой, тип которой мы приводим. Когда мы выполняем арифметические операции над числами разной разрядности, мы то же, неявно УКАЗЫВАЕМ компилятору на разрядность операции... А если компилятор начнет предполагать, что после инкремента какой то переменной может произойти переполнение разрядной сетки, то все переменные, в конечном итоге, у него превратятся в LONGLONGLONGLONGLONG..................... Для того, что бы проверить код, не обязательно иметь ИАР Си, возьмите от Борланда или Мелкософта... Цитата(rezident @ Nov 6 2006, 19:57)  Цитата из K&R (переводная, из библиотеки Мошкова). Глава 1.6. МассивыЦитата По определению перед проведением арифметических опера- ций, вовлекающих переменные типа CHAR и INT, все они преоб- разуются к типу INT, TAK что в арифметических выражениях пе- ременные типа CHAR по существу идентичны переменным типа INT. Еще раз предлагаю инкремент индекса вынести как отдельную операцию. У меня нет IAR for AVR, чтобы проверить получившийся результат на ассемблере. К сожалению, не читал данное произведение... И хотя инкремент индекса, в приципе тоже арифметическая операция, ИМХО никогда любой нормальный компилятор не преобразует индекс при инкременте в переменную бОльшей разрядности... Может быть только, если этот компилятор написан Вами)
--------------------
|
|
|
|
|
Nov 8 2006, 08:06
|
Местный
  
Группа: Свой
Сообщений: 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 однобайтовая переменная, а значит добавленная строка вообще не влияет на результат, либо её добавляют не после "этого", а перед "этим"! Ну да ладно читаем дальше. Цитата начинается какая-то свистопляска, оно выводит содержимое буфера еще раз... А "оно" и должно выводить ещё раз! Индекс то обнулился!  Цитата И хотя инкремент индекса, в приципе тоже арифметическая операция Было сказано про арифметические операции в которых участвуют переменные разных типов
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|