|
|
  |
Обращение к элементу двухмерного массива используя адрес массива |
|
|
|
Dec 28 2010, 18:49
|

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

|
QUOTE (ViKo @ Dec 28 2010, 22:55)  В любом случае, эти два способа работают по-разному. А вы сравните for (int32_t j=9; j>=0; j--) GPIOA->ODR = pDig[j]; и for (int32_t j=9; j>=0; j--) GPIOA->ODR = Digit[j];
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Dec 28 2010, 18:58
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
Цитата(Сергей Борщ @ Dec 28 2010, 23:49)  А вы сравните... Код ;;;202 static const uint8_t Digit[10] = {'0','1','2','3','4','5','6','7','8','9'}; ;;;203 const uint8_t *pDig = Digit; 000092 4870 LDR r0,|L1.596| ;;;204 for (int32_t j=9; j>=0; j--) GPIOA->ODR = *(pDig++); 000094 4970 LDR r1,|L1.600| 000096 2209 MOVS r2,#9 |L1.152| 000098 f8103b01 LDRB r3,[r0],#1 00009c f8c1380c STR r3,[r1,#0x80c] 0000a0 1e52 SUBS r2,r2,#1 0000a2 d5f9 BPL |L1.152| 0000a4 4a6b LDR r2,|L1.596| ;;;205 for (int32_t j=9; j>=0; j--) GPIOA->ODR = Digit[j]; 0000a6 2009 MOVS r0,#9 |L1.168| 0000a8 5c13 LDRB r3,[r2,r0] 0000aa f8c1380c STR r3,[r1,#0x80c] 0000ae 1e40 SUBS r0,r0,#1 0000b0 d5fa BPL |L1.168| Это ничего не меняет. Отличия именно в адресации элементов массива. Похоже, разработчики ARM специально "подрихтовали" процессор под C.
|
|
|
|
|
Dec 28 2010, 19:03
|
.
     
Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753

|
Цитата(ViKo @ Dec 29 2010, 01:55)  Результат слегка обескуражил. Обращение к элементу массива с помощью индекса занимает меньше байтов. Особенность системы команд ARM. Не надо все системы команд ARM-ов обобщать. Это система кортекса-М3. Для ARM v4 32 бита одинаковое кол-во слов, команд и тактов. А во-вторых, алгоритмы в примерах разные. В первом инкремент указателя, во втором взятие элементов с конца массива. В-третьих нафига козе баян в виде скобок *(pDig++) ? Попробуйте без них *pDig++ Цитата(XVR @ Dec 29 2010, 01:23)  В случает ТС разница между *** и **[] будет катастрофическая Что такое ТС? "В случает ТС"
--------------------
Заблуждаться - Ваше законное право :-)
|
|
|
|
|
Dec 28 2010, 19:11
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
Цитата(GetSmart @ Dec 29 2010, 00:03)  Не надо все системы команд ARM-ов обобщать. Это система кортекса-М3. Для ARM v4 32 бита одинаковое кол-во слов, команд и тактов. А во-вторых, алгоритмы в примерах разные. В первом инкремент указателя, во втором взятие элементов с конца массива. В-третьих нафига козе баян в виде скобок *(pDig++) ? Попробуйте без них *pDig++ Насчет скобок - согласен, можно без них. Просто тяжелее воспринимать. Убрал. В книжках их, кстати, пишут. По той же причине. Насчет взятия элементов с конца массива - упустил из виду. Не сомневаюсь, что результат не изменится. Зря не сомневался  Начинать-то нужно с нуля, потом инкрементировать счетчик и сравнивать с 10. Стало на 2 байта больше. А система команд - Thumb-2 называется. Виноват. Имел в виду систему команд от фирмы ARM. Опять же, это чисто качественный пример. Для ARMv4 команды для двух арифметик тоже будут разные.
|
|
|
|
|
Dec 28 2010, 19:40
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(ViKo @ Dec 29 2010, 00:58)  Похоже, разработчики ARM специально "подрихтовали" процессор под C. Все с точностью до наоборот...  Большая часть кода С(когда-то написанного) используют адресную арифметику т.к. на большинстве процессоров/компиляторов это дает выигрыш. А Ваш пример действительно интересен, надо будет не забыть поиграться с этим при переносе проекта на кортекс.
|
|
|
|
|
Dec 29 2010, 05:26
|

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

|
QUOTE (ViKo @ Dec 28 2010, 23:58)  Это ничего не меняет. Отличия именно в адресации элементов массива. Да что ж вы сравниваете два алгоритма и удивляетесь разнице? Еще раз говорю, сравните в одинаковом цикле обращение pDig[j] и Digit[j], сравните *(pDig + j) и *(Digit + j), а потом посмотрите на оба варианта исходного текста CODE (int32_t j=9; j>=0; j--) GPIOA->ODR = *(pDig + j); и (int32_t j=9; j>=0; j--) GPIOA->ODR = *(Digit + j); или CODE (int32_t j=9; j>=0; j--) GPIOA->ODR = pDig[j]; и (int32_t j=9; j>=0; j--) GPIOA->ODR = Digit[j]; и подумайте: не видя объявления pDig и Digit вы только глядя на их использование сможете сказать, который из них массив, а который указатель? Нет, не сможете. Вот это я и пытаюсь объяснить на протяжении двух страниц. QUOTE (XVR @ Dec 28 2010, 22:23)  В случает ТС разница между *** и **[] будет катастрофическая Не верю. Покажите ее. Аргументируйте утверждение. С указателем получается так: CODE #define PROFILE ((sub_profile ***)(0x0801F000))
void test() { unsigned int volatile temp; temp = PROFILE[1][0]->type; }
166 0000 18309FE5 ldr r3, .L7 @ tmp137, 167 0004 043093E5 ldr r3, [r3, #4] @ tmp138, 168 0008 003093E5 ldr r3, [r3, #0] @ tmp139, 169 000c B030D3E1 ldrh r3, [r3, #0] @ temp.29, D.3609_3->type
186 .L7: 187 0020 00F00108 .word 134344704
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Dec 29 2010, 06:59
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
Цитата(Сергей Борщ @ Dec 29 2010, 10:26)  Да что ж вы сравниваете два алгоритма и удивляетесь разнице? Еще раз говорю, сравните в одинаковом цикле обращение pDig[j] и Digit[j], сравните *(pDig + j) и *(Digit + j... не видя объявления pDig и Digit вы только глядя на их использование сможете сказать, который из них массив, а который указатель? Нет, не сможете. Вот это я и пытаюсь объяснить на протяжении двух страниц. Так я ж не спорю о том, что Digit[j] и *(Digit + j) - это одно и то же. Наоборот, подтверждал.  А удивляюсь я тому, что известное правило отказываться от индексной арифметики в пользу адресной для ARM не работает. Может быть, для многомерных массивов все "вернется на круги своя"... Цитата(XVR @ Dec 29 2010, 10:50)  за исключением того, что конструкция **[] отказывается компилится Должна компилироваться!:) Скорее всего, что-то не так определено.
|
|
|
|
|
Dec 29 2010, 16:54
|
Гуру
     
Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847

|
Цитата(ViKo @ Dec 29 2010, 12:59)  Должна компилироваться!:) Скорее всего, что-то не так определено. Не должно: Цитата t.cc: In function 'void test()': t.cc:10:12: error: ISO C++ forbids casting to an array type 'sub_profile** []' Для С аналогично (текст сообщения об ошибке немного другой, но смысл тот же)
|
|
|
|
|
Dec 30 2010, 07:21
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
Цитата(XVR @ Dec 29 2010, 21:54)  Не должно: Такое годится? Трудно понять, но, кажется, делает, что задумано. Ни ошибок, ни предупреждений. Код static const uint8_t a = 'A', b = 'B', c = 'C', d = 'D'; static const uint8_t *pa = &a, *pb = &b, *pc = &c, *pd = &d; static const uint8_t **ptr[] = {&pa, &pb, &pc, &pd}; for (int32_t i=0; i<4; i++) GPIOA->ODR = **ptr[i]; Результат компиляции: Код ;;;210 static const uint8_t a = 'A', b = 'B', c = 'C', d = 'D'; ;;;211 static const uint8_t *pa = &a, *pb = &b, *pc = &c, *pd = &d; ;;;212 static const uint8_t **ptr[] = {&pa, &pb, &pc, &pd}; ;;;213 for (int32_t i=0; i<4; i++) GPIOA->ODR = **ptr[i]; 0000b4 4965 LDR r1,|L1.588| 0000b6 2000 MOVS r0,#0 0000b8 3120 ADDS r1,r1,#0x20 |L1.186| 0000ba f8513020 LDR r3,[r1,r0,LSL #2] 0000be 681b LDR r3,[r3,#0] 0000c0 781b LDRB r3,[r3,#0] 0000c2 f8c2380c STR r3,[r2,#0x80c] 0000c6 1c40 ADDS r0,r0,#1 0000c8 2804 CMP r0,#4 0000ca dbf6 BLT |L1.186|
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|