xvr 12 28 декабря, 2010 Опубликовано 28 декабря, 2010 · Жалоба Решил сравнить адресную и индексную арифметику на приведенном выше своем примере. Результат слегка обескуражил. Обращение к элементу массива с помощью индекса занимает меньше байтов. Особенность системы команд ARM. Включите оптимизацию при компиляции, результат должен стать похожим в обоих случаях. Компиляторы обычно довольно умные, что бы автоматически конвертировать индексацию в разъименование указателей и обратно, в зависимости от архитектуры и контекста применения Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 28 декабря, 2010 Опубликовано 28 декабря, 2010 · Жалоба Включите оптимизацию при компиляции, результат должен стать похожим в обоих случаях. Компиляторы обычно довольно умные, что бы автоматически конвертировать индексацию в разъименование указателей и обратно, в зависимости от архитектуры и контекста применения То, что показал - лучшее. Прошелся по всем вариантам оптимизации. На мой взгляд, компилятор не должен быть настолько умным, как вы говорите. :) Еще попробовал заменить тип переменных в массиве на uint16_t и uint32_t. В первом случае коды для адресной и индексной арифметик сравнялись, а во втором индексная арифметика опять вырвалась вперед. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 143 28 декабря, 2010 Опубликовано 28 декабря, 2010 · Жалоба В любом случае, эти два способа работают по-разному.А вы сравните for (int32_t j=9; j>=0; j--) GPIOA->ODR = pDig[j]; и for (int32_t j=9; j>=0; j--) GPIOA->ODR = Digit[j]; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 28 декабря, 2010 Опубликовано 28 декабря, 2010 · Жалоба А вы сравните... ;;;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. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GetSmart 0 28 декабря, 2010 Опубликовано 28 декабря, 2010 · Жалоба Результат слегка обескуражил. Обращение к элементу массива с помощью индекса занимает меньше байтов. Особенность системы команд ARM. Не надо все системы команд ARM-ов обобщать. Это система кортекса-М3. Для ARM v4 32 бита одинаковое кол-во слов, команд и тактов. А во-вторых, алгоритмы в примерах разные. В первом инкремент указателя, во втором взятие элементов с конца массива. В-третьих нафига козе баян в виде скобок *(pDig++) ? Попробуйте без них *pDig++ В случает ТС разница между *** и **[] будет катастрофическая Что такое ТС? "В случает ТС" Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 28 декабря, 2010 Опубликовано 28 декабря, 2010 · Жалоба Не надо все системы команд ARM-ов обобщать. Это система кортекса-М3. Для ARM v4 32 бита одинаковое кол-во слов, команд и тактов. А во-вторых, алгоритмы в примерах разные. В первом инкремент указателя, во втором взятие элементов с конца массива. В-третьих нафига козе баян в виде скобок *(pDig++) ? Попробуйте без них *pDig++ Насчет скобок - согласен, можно без них. Просто тяжелее воспринимать. Убрал. В книжках их, кстати, пишут. По той же причине. Насчет взятия элементов с конца массива - упустил из виду. Не сомневаюсь, что результат не изменится. Зря не сомневался :) Начинать-то нужно с нуля, потом инкрементировать счетчик и сравнивать с 10. Стало на 2 байта больше. А система команд - Thumb-2 называется. Виноват. Имел в виду систему команд от фирмы ARM. Опять же, это чисто качественный пример. Для ARMv4 команды для двух арифметик тоже будут разные. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
singlskv 0 28 декабря, 2010 Опубликовано 28 декабря, 2010 · Жалоба Похоже, разработчики ARM специально "подрихтовали" процессор под C.Все с точностью до наоборот... :) Большая часть кода С(когда-то написанного) используют адресную арифметику т.к. на большинстве процессоров/компиляторов это дает выигрыш. А Ваш пример действительно интересен, надо будет не забыть поиграться с этим при переносе проекта на кортекс. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 143 29 декабря, 2010 Опубликовано 29 декабря, 2010 · Жалоба Это ничего не меняет. Отличия именно в адресации элементов массива.Да что ж вы сравниваете два алгоритма и удивляетесь разнице? Еще раз говорю, сравните в одинаковом цикле обращение pDig[j] и Digit[j], сравните *(pDig + j) и *(Digit + j), а потом посмотрите на оба варианта исходного текста (int32_t j=9; j>=0; j--) GPIOA->ODR = *(pDig + j); и (int32_t j=9; j>=0; j--) GPIOA->ODR = *(Digit + j); или (int32_t j=9; j>=0; j--) GPIOA->ODR = pDig[j]; и (int32_t j=9; j>=0; j--) GPIOA->ODR = Digit[j]; и подумайте: не видя объявления pDig и Digit вы только глядя на их использование сможете сказать, который из них массив, а который указатель? Нет, не сможете. Вот это я и пытаюсь объяснить на протяжении двух страниц. В случает ТС разница между *** и **[] будет катастрофическаяНе верю. Покажите ее. Аргументируйте утверждение. С указателем получается так:#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 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
xvr 12 29 декабря, 2010 Опубликовано 29 декабря, 2010 · Жалоба Не верю. Покажите ее.Посыпаю голову пеплом - разницы действительно нет (за исключением того, что конструкция **[] отказывается компилится). Разница проявляется в другом контексте 2 GetSmart: ТС - это 'Топик Стартер' Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 29 декабря, 2010 Опубликовано 29 декабря, 2010 · Жалоба Да что ж вы сравниваете два алгоритма и удивляетесь разнице? Еще раз говорю, сравните в одинаковом цикле обращение pDig[j] и Digit[j], сравните *(pDig + j) и *(Digit + j... не видя объявления pDig и Digit вы только глядя на их использование сможете сказать, который из них массив, а который указатель? Нет, не сможете. Вот это я и пытаюсь объяснить на протяжении двух страниц. Так я ж не спорю о том, что Digit[j] и *(Digit + j) - это одно и то же. Наоборот, подтверждал. :) А удивляюсь я тому, что известное правило отказываться от индексной арифметики в пользу адресной для ARM не работает. Может быть, для многомерных массивов все "вернется на круги своя"... за исключением того, что конструкция **[] отказывается компилится Должна компилироваться!:) Скорее всего, что-то не так определено. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
xvr 12 29 декабря, 2010 Опубликовано 29 декабря, 2010 · Жалоба Должна компилироваться!:) Скорее всего, что-то не так определено. Не должно: t.cc: In function 'void test()': t.cc:10:12: error: ISO C++ forbids casting to an array type 'sub_profile** []' Для С аналогично (текст сообщения об ошибке немного другой, но смысл тот же) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 30 декабря, 2010 Опубликовано 30 декабря, 2010 · Жалоба Не должно: Такое годится? Трудно понять, но, кажется, делает, что задумано. Ни ошибок, ни предупреждений. 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| Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sigmaN 0 30 декабря, 2010 Опубликовано 30 декабря, 2010 · Жалоба ага, только эти a b c тоже как-бээ массивы указателей должны быть ) у ТС профиль - это массив указателей на подпрофили, а дефайн этот указывает на массив профилей... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 30 декабря, 2010 Опубликовано 30 декабря, 2010 · Жалоба В тему указатели-массивы (накидал примерчик за 5 минут): uint8_t* get_first_middle_of_tripple(uint8_t* p, size_t qty) { if (qty>=3) { while (qty--) { p++; if ((p[0] == p[-1]) && (p[0] == p[1])) { return (p); } } } return (NULL); } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GetSmart 0 30 декабря, 2010 Опубликовано 30 декабря, 2010 · Жалоба 36? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться