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

 
 
5 страниц V  « < 2 3 4 5 >  
Reply to this topicStart new topic
> Обращение к элементу двухмерного массива используя адрес массива
XVR
сообщение Dec 28 2010, 18:06
Сообщение #46


Гуру
******

Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847



Цитата(ViKo @ Dec 28 2010, 23:55) *
Решил сравнить адресную и индексную арифметику на приведенном выше своем примере.
Результат слегка обескуражил. Обращение к элементу массива с помощью индекса занимает меньше байтов.
Особенность системы команд ARM.
Включите оптимизацию при компиляции, результат должен стать похожим в обоих случаях. Компиляторы обычно довольно умные, что бы автоматически конвертировать индексацию в разъименование указателей и обратно, в зависимости от архитектуры и контекста применения

Go to the top of the page
 
+Quote Post
ViKo
сообщение Dec 28 2010, 18:30
Сообщение #47


Универсальный солдатик
******

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



Цитата(XVR @ Dec 28 2010, 23:06) *
Включите оптимизацию при компиляции, результат должен стать похожим в обоих случаях. Компиляторы обычно довольно умные, что бы автоматически конвертировать индексацию в разъименование указателей и обратно, в зависимости от архитектуры и контекста применения

То, что показал - лучшее. Прошелся по всем вариантам оптимизации. На мой взгляд, компилятор не должен быть настолько умным, как вы говорите. sm.gif
Еще попробовал заменить тип переменных в массиве на uint16_t и uint32_t. В первом случае коды для адресной и индексной арифметик сравнялись, а во втором индексная арифметика опять вырвалась вперед.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Dec 28 2010, 18:49
Сообщение #48


Гуру
******

Группа: Модераторы
Сообщений: 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)
Go to the top of the page
 
+Quote Post
ViKo
сообщение Dec 28 2010, 18:58
Сообщение #49


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 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.
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Dec 28 2010, 19:03
Сообщение #50


.
******

Группа: Участник
Сообщений: 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) *
В случает ТС разница между *** и **[] будет катастрофическая

Что такое ТС? "В случает ТС"


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
ViKo
сообщение Dec 28 2010, 19:11
Сообщение #51


Универсальный солдатик
******

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



Цитата(GetSmart @ Dec 29 2010, 00:03) *
Не надо все системы команд ARM-ов обобщать. Это система кортекса-М3. Для ARM v4 32 бита одинаковое кол-во слов, команд и тактов.
А во-вторых, алгоритмы в примерах разные. В первом инкремент указателя, во втором взятие элементов с конца массива.
В-третьих нафига козе баян в виде скобок *(pDig++) ?
Попробуйте без них *pDig++

Насчет скобок - согласен, можно без них. Просто тяжелее воспринимать. Убрал. В книжках их, кстати, пишут. По той же причине.
Насчет взятия элементов с конца массива - упустил из виду. Не сомневаюсь, что результат не изменится. Зря не сомневался sm.gif Начинать-то нужно с нуля, потом инкрементировать счетчик и сравнивать с 10. Стало на 2 байта больше.
А система команд - Thumb-2 называется. Виноват. Имел в виду систему команд от фирмы ARM. Опять же, это чисто качественный пример. Для ARMv4 команды для двух арифметик тоже будут разные.
Go to the top of the page
 
+Quote Post
singlskv
сообщение Dec 28 2010, 19:40
Сообщение #52


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(ViKo @ Dec 29 2010, 00:58) *
Похоже, разработчики ARM специально "подрихтовали" процессор под C.
Все с точностью до наоборот... sm.gif
Большая часть кода С(когда-то написанного) используют адресную арифметику т.к. на
большинстве процессоров/компиляторов это дает выигрыш.
А Ваш пример действительно интересен, надо будет не забыть поиграться с этим
при переносе проекта на кортекс.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Dec 29 2010, 05:26
Сообщение #53


Гуру
******

Группа: Модераторы
Сообщений: 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)
Go to the top of the page
 
+Quote Post
XVR
сообщение Dec 29 2010, 05:50
Сообщение #54


Гуру
******

Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847



Цитата(Сергей Борщ @ Dec 29 2010, 11:26) *
Не верю. Покажите ее.
Посыпаю голову пеплом - разницы действительно нет (за исключением того, что конструкция **[] отказывается компилится). Разница проявляется в другом контексте


2 GetSmart: ТС - это 'Топик Стартер'
Go to the top of the page
 
+Quote Post
ViKo
сообщение Dec 29 2010, 06:59
Сообщение #55


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 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) - это одно и то же. Наоборот, подтверждал. sm.gif А удивляюсь я тому, что известное правило отказываться от индексной арифметики в пользу адресной для ARM не работает. Может быть, для многомерных массивов все "вернется на круги своя"...

Цитата(XVR @ Dec 29 2010, 10:50) *
за исключением того, что конструкция **[] отказывается компилится

Должна компилироваться!:) Скорее всего, что-то не так определено.
Go to the top of the page
 
+Quote Post
XVR
сообщение Dec 29 2010, 16:54
Сообщение #56


Гуру
******

Группа: Свой
Сообщений: 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** []'
Для С аналогично (текст сообщения об ошибке немного другой, но смысл тот же)
Go to the top of the page
 
+Quote Post
ViKo
сообщение Dec 30 2010, 07:21
Сообщение #57


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 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|
Go to the top of the page
 
+Quote Post
sigmaN
сообщение Dec 30 2010, 07:58
Сообщение #58


I WANT TO BELIEVE
******

Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751



ага, только эти a b c тоже как-бээ массивы указателей должны быть ) у ТС профиль - это массив указателей на подпрофили, а дефайн этот указывает на массив профилей...


--------------------
The truth is out there...
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Dec 30 2010, 08:09
Сообщение #59


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



В тему указатели-массивы (накидал примерчик за 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);
}


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Dec 30 2010, 12:04
Сообщение #60


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



36?


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post

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

 


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


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