Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Обращение к элементу двухмерного массива используя адрес массива
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
Страницы: 1, 2
LEVENVORF
Код
//Структура описывающая подпрофиль
typedef struct {
  unsigned short type;
  unsigned short signal;
} sub_profile;

//Массив подпрофиля 1
const sub_profile SUB_PROFILE_1 = {
330,
400
};

//Массив подпрофиля 2
const sub_profile SUB_PROFILE_2 = {
100,
1200
};

......

//Массив подпрофиля n
const sub_profile SUB_PROFILE_n = {
1,
2
};

Массив профиля состоящий из указателей на подпрофили
Код
const sub_profile * PROFILE_1[] = {&SUB_PROFILE_1, &SUB_PROFILE_2, ... , &SUB_PROFILE_n, 0};

И еще один массив содержащий указатели на профили
Код
const sub_profile ** PROFILE[] = {PROFILE_1, ... , PROFILE_n, 0};

Массив PROFILE[] не объявлен, но известно что он начинается с адреса 0x0801F000 (по этому адресу он записывается при помощи другого проекта).
Каким образом я могу обратиться к элементу структуры определенного подпрофиля, определенного профиля.
При попытке:
Код
#define PROFILE                ((sub_profile **)(0x0801F000))

unsigned int temp;
  
temp = PROFILE[1][0]->type;

IAR ARM 5.50 выдает ошибку expression must have pointer type
rezident
Цитата(LEVENVORF @ Dec 24 2010, 22:13) *
IAR ARM 5.50 выдает ошибку expression must have pointer type
Все верно. Значением указателя на указатель является адрес указателя. При попытке напрямую присвоить обычной переменной значение указателя (адрес) и возникает ошибка. Если вам непременно необходимо такое присваивание, то сделайте явное приведение типа к типу переменной. Только предварительно удостоверьтесь, что тип int в вашей системе имеет размерность не меньше, чем адрес переменной.
LEVENVORF
int для stm32f 4-х байтный.

Так как же мне все-таки вычитать значение элемента структуры?
rezident
Цитата(LEVENVORF @ Dec 26 2010, 02:33) *
Так как же мне все-таки вычитать значение элемента структуры?
Используя указатель. Значение из массива указателей нужно присваивать переменной имеющий такой же тип указателя и затем использовать обращение через этот указатель к массиву элементов.
LEVENVORF
Попробовал вот так:
Код
#define PROFILE                ((sub_profile **)(0x0801F000))

sub_profile*  temp;
unsigned short temp2;
  
temp = PROFILE[1];
temp2 = (temp[0])->type;

Не помогло. Ошибка такая же.
Что неправильно?
rezident
На какую именно строку ругается?
sigmaN
ну так чтобы из указателя на указатель получить указатель - разыменовать то надо бы по идее ))
Код
temp = *PROFILE[1];
как-то так, чтоли..
LEVENVORF
Цитата(rezident @ Dec 26 2010, 01:35) *
На какую именно строку ругается?

Код
temp2 = (temp[0])->type;

rezident
А если так?
Код
temp2 = temp[0].type;

temp[0] уже получает значение адреса структуры, а чтобы извлечь элемент структуры нужно применить "." (оператор "точка"). Вы же пытаетесь адрес самой структуры применить как указатель на элемент структуры, но он им не является.
LEVENVORF
Цитата(rezident @ Dec 26 2010, 02:06) *
А если так?
Код
temp2 = temp[0].type;

temp[0] уже получает значение адреса структуры, а чтобы извлечь элемент структуры нужно применить "." (оператор "точка"). Вы же пытаетесь адрес самой структуры применить как указатель на элемент структуры, но он им не является.


Откомпилировалось rolleyes.gif , но работает неправильно crying.gif
temp2 приняло значение первых двух байт temp[0], а это не значение элемента структуры, а кусок (потому что temp2 типа short) адреса структуры.
sigmaN
Разыменовывать, разыменовывать же)
вот это даже проверил(правда на gcc)
Код
//Структура описывающая подпрофиль
typedef struct {
  unsigned short type;
  unsigned short signal;
} sub_profile;

//Массив подпрофиля 1
const sub_profile SUB_PROFILE_1 = {
330,
400
};

//Массив подпрофиля 2
const sub_profile SUB_PROFILE_2 = {
100,
1200
};

const sub_profile *PROFILE_1[] = {&SUB_PROFILE_1, &SUB_PROFILE_2, 0};


//сюда во время своего эксперимента я подставлял свой адрес. Но сути дела это не меняет ))
#define PROFILE                ((sub_profile **)(0x0801F000))

//у Вас тут был int, а не  short...
unsigned short temp;

void main(void){
//тут мыслил так:
//сперва разыменовываем PROFILE, чтобы указатель на указатель превратился просто в указатель (*PROFILE)
//далее, этот разименованый указатель приводим к типу (sub_profile *), чтобы компилятор трактовал новоиспеченный указатель
//как указывающий на тип sub_profile *
//далее уже(после приведения типа) к этому указателю можно обратиться как к массиву используя известную фишку Си [0]
//также известно, что после применения этой фишки нам уже нужно использовать не ->, а .
//вот, собственно и имеем результат
    temp = (sub_profile *)(*PROFILE)[0].type; //temp == 330
}
LEVENVORF
не компилируется. ругается на строку:
Цитата(sigmaN @ Dec 26 2010, 06:11) *
Код
temp = (sub_profile *)(*PROFILE)[0].type;

a value of type "sub_profile*" cannot be assigned to an entity of type "unsigned short"
rezident
Ну вот так точно уж должно работать
Код
#define PROFILE                ((sub_profile **)(0x0801F000))

unsigned short temp;
sub_profile **pptr, *pntr;

  pptr = PROFILE; // инициализируем указатель
  pptr = (sub_profile **)(pptr[1]); // извлекаем из массива указатель на требуемый массив указателей
  pntr = (sub_profile *)(*pptr); // извлекаем из массива указателей требуемый указатель на структуру
  temp = pntr[1].type; //извлекаем элемент структуры

Тут все по-отдельности, но типизация соответствует.
sigmaN
Цитата
не компилируется. ругается на строку:
компилятору незачёт )) проверить всё не получится ибо IARa нет у меня.
rezident
Вот так тоже работает, но лично меня сложность такой конструкции несколько угнетает sm.gif
Код
temp = ((sub_profile *)(*(sub_profile **)PROFILE[1]))[1].type;
sigmaN
Топикстартер, а нам вообще точно нужен указатель на указатель?
Предлагаю избавиться от этого изврата ещё в самом начале
может быть пусть #define PROFILE будет void * а потом, где надо его можно будет преобразовать во что надо..

И вообще мне интересо, почему Ваш этот ИАР не хавает предложенный мною вариант... вроде там всё по Сишному правильно....какого он, извиняюсь, икса....
rezident
Цитата(sigmaN @ Dec 27 2010, 02:36) *
И вообще мне интересо, почему Ваш этот ИАР не хавает предложенный мною вариант... вроде там всё по Сишному правильно....какого он, извиняюсь, икса....
Дык там скобочек не хватает. Вот так не ругается
Код
temp = ((sub_profile *)(*PROFILE))[0].type; //temp == 330

правда и не работает как хотелось бы ТС rolleyes.gif
sigmaN
я то проверял и у меня реально работало же. могу хоть щас полный проект выложить(правда под авр). Но в эмуляторе всё проверил - работает как надо.
rezident
Цитата(sigmaN @ Dec 27 2010, 03:36) *
я то проверял и у меня реально работало же. могу хоть щас полный проект выложить(правда под авр). Но в эмуляторе всё проверил - работает как надо.
Если вас IAR не впечатляет, но быть может убедит авторитет Keil? Так вот Keil выдает такую же ошибку на вашу строку, что и IAR. В то время как мои 4-х и 1-но строчные варианты компилируются и работают без ошибок и там и там. Проверял в IAR EWARM 5.50.5 и Keil 4.12.
sigmaN
тогда наверное дело в размере указателя.... щас найду кеил.. точно был
LEVENVORF
компилируется и работает.
Цитата(rezident @ Dec 26 2010, 22:38) *
Ну вот так точно уж должно работать
Код
#define PROFILE                ((sub_profile **)(0x0801F000))

unsigned short temp;
sub_profile **pptr, *pntr;

  pptr = PROFILE; // инициализируем указатель
  pptr = (sub_profile **)(pptr[1]); // извлекаем из массива указатель на требуемый массив указателей
  pntr = (sub_profile *)(*pptr); // извлекаем из массива указателей требуемый указатель на структуру
  temp = pntr[1].type; //извлекаем элемент структуры

Тут все по-отдельности, но типизация соответствует.


компилируется и тоже работает.
Цитата(rezident @ Dec 26 2010, 23:17) *
Вот так тоже работает, но лично меня сложность такой конструкции несколько угнетает sm.gif
Код
temp = ((sub_profile *)(*(sub_profile **)PROFILE[1]))[1].type;


ОГРОМНОЕ СПАСИБО!!!
sigmaN
скобок действительно не хватало и похоже, что на любом компиляторе, кроме AVR GCC мой код не компилился.
Но я сделал вот так
Код
temp = ((sub_profile *)(*PROFILE))[0].type; //temp == 330
temp = ((sub_profile *)(*PROFILE))[1].type; //temp == 100
и дело пошло. Даже в микрософтовской визуал студии всё работает правильно.

added кажется надо больше спать. ТС говорил о том, что массив содержит массив указателей на профили, да... понял. молчу. ))
Сергей Борщ
QUOTE (sigmaN @ Dec 27 2010, 02:18) *
Но я сделал вот так
CODE
temp = ((sub_profile *)(*PROFILE))[0].type; //temp == 330
temp = ((sub_profile *)(*PROFILE))[1].type; //temp == 100
и дело пошло. Даже в микрософтовской визуал студии всё работает правильно.
Что-то вас всех куда-то понесло в дебри
CODE
    #define PROFILE                ((sub_profile ***)(0x0801F000))
    unsigned int temp;

    temp = PROFILE[1][0]->type;
LEVENVORF
Цитата(Сергей Борщ @ Dec 27 2010, 10:01) *
Что-то вас всех куда-то понесло в дебри
Код
    #define PROFILE                ((sub_profile ***)(0x0801F000))
    unsigned int temp;
    temp = PROFILE[1][0]->type;

Спасибо. Очень красивый вариант. Почти точно такой предложили сотрудники на работе.
Еще раз спасибо!!!!
sigmaN
temp = PROFILE[1][0]->type;
даа, а ведь и правда так и должно было быть.
Сергей Борщ
QUOTE (LEVENVORF @ Dec 27 2010, 12:39) *
Почти точно такой предложили сотрудники на работе.
Так он у вас и был изначально. Вы просто в #define забыли добавить еще один указатель, ведь ваш переопределенный PROFILE есть указатель на массив указателей на массивы указателей на субпрофили.
demiurg_spb
Есть очень хорошее правило, прочитанное мной где-то давным-давно:
"По возможности не использовать более 2 степеней вложенности указателей".
Максимум - это указатель на указатель.
И жизнь будет намного проще:-)
XVR
Цитата(Сергей Борщ @ Dec 27 2010, 11:01) *
Что-то вас всех куда-то понесло в дебри
Код
    #define PROFILE                ((sub_profile ***)(0x0801F000))
    unsigned int temp;
    temp = PROFILE[1][0]->type;
Почти так, но не совсем. Последняя размерность - это массив, а не указатель. Должно быть как то так:
Код
    #define PROFILE                ((sub_profile **[])(0x0801F000))
    unsigned int temp;
    temp = PROFILE[1][0]->type;

Если компилятор не прожует, то так:
Код
        typedef sub_profile **ProfileType[];
    #define PROFILE                ((ProfileType)(0x0801F000))
    unsigned int temp;
    temp = PROFILE[1][0]->type;

sigmaN
Цитата
Есть очень хорошее правило, прочитанное мной где-то давным-давно:
"По возможности не использовать более 2 степеней вложенности указателей".
Ну мне эта конструкция тоже сразу не очень понравилась... но раз уж там все эти профайлы так закручены by design - то не известно что проще...переделывать дизайн или такой вот "костыль"(конечно с натяжкой) вставить.
Сергей Борщ
QUOTE (XVR @ Dec 27 2010, 18:58) *
Почти так, но не совсем. Последняя размерность - это массив, а не указатель. Должно быть как то так:
В Си массивы и указатели почти эквивалентные понятия. Используется одна и та же адресная арифметика
CODE
int a[5];
int *b = a;

*(a + 3) = 5;
b[3] = 5;
3[a] = 5;

ViKo
Цитата(Сергей Борщ @ Dec 27 2010, 23:58) *
В Си массивы и указатели почти эквивалентные понятия. Используется одна и та же адресная арифметика

Только для массивов имеется две переменные - адрес начала массива и индекс, которые складываются согласно типу переменных массива. А для указателей имеется всего одна переменная - адрес, соответствующий типу переменной, на которую указывает указатель.
Сергей Борщ
QUOTE (ViKo @ Dec 28 2010, 12:26) *
Только для массивов имеется две переменные - адрес начала массива и индекс, которые складываются согласно типу переменных массива. А для указателей имеется всего одна переменная - адрес, соответствующий типу переменной, на которую указывает указатель.
Для массива имеется одна переменная - адрес начала. И он фактически имеет тип "указатель на тип элемента массива". Индекс появляется при обращении к элементу. При обращении по указателю точно так же можно использовать нотацию обращения к элементу массива как и при обращении к элементу массива можно использовать нотацию указателей. Пример подобных обращений в предыдущем сообщении. Вы можете написать как *b, так и b[0], эти записи совершенно эквивалентны в C. Массив и константный указатель отличаются только на этапе объявления/инициализации. http://www.fredosaurus.com/notes-cpp/array...aspointers.html
ViKo
Цитата(Сергей Борщ @ Dec 28 2010, 13:00) *
Для массива имеется одна переменная - адрес начала. И он фактически имеет тип "указатель на тип элемента массива". Индекс появляется при обращении к элементу. При обращении по указателю точно так же можно использовать нотацию обращения к элементу массива как и при обращении к элементу массива можно использовать нотацию указателей. Пример подобных обращений в предыдущем сообщении. Вы можете написать как *b, так и b[0], эти записи совершенно эквивалентны в C. Массив и константный указатель отличаются только на этапе объявления/инициализации. http://www.fredosaurus.com/notes-cpp/array...aspointers.html

Я согласен с вашими словами, однако, массив обрабатывается обычно именно по его адресу и индексу. Т.е., например, в каждом шаге цикла, обрабатывающего массив, вычисляется адрес элемента массива, с использованием адреса начала массива и индекса.
Если указатель можно просто перемещать по элементам массива (адресная арифметика), то при индексной арифметике адрес элемента массива нужно вычислить по адресу начала массива и индексу элемента, для этого задействовать некую временную переменную (регистр микропроцессора). Для ARM, к примеру, эта операция выполняется в одной команде, а для PIC16 команд потребуется несколько.
rezident
Цитата(Сергей Борщ @ Dec 28 2010, 02:58) *
В Си массивы и указатели почти эквивалентные понятия. Используется одна и та же адресная арифметика
Это справедливо только для случая массива и указателя на элемент массива. Различие заключается в том, что массив состоит из элементов одинаковой размерности, а указатель можно использовать для обращения и к элементам объектов с более сложным устройством - структуры, например. Элементы структуры могут иметь совершенно разную размерность и в т.ч. включать в себя те же массивы. Для обращения к структуре недостаточно знать только лишь ее базовый адрес, нужно знать и ее внутреннее устройство, чтобы правильно вычислять значение указателя.
Сергей Борщ
QUOTE (rezident @ Dec 28 2010, 16:43) *
Различие заключается в том, что массив состоит из элементов одинаковой размерности, а указатель можно использовать для обращения и к элементам объектов с более сложным устройством - структуры, например.
Какая разница? Массив тоже может состоять из структур. Теперь я беру константный указатель на эту структуру и присваиваю ему адрес начала этого массива (пишу mystruct * const ptr = array;). Найдите мне теперь любое действие, которое я могу выполнить с ptr и не могу выполнить с array. Или наоборот.
rezident
Цитата(Сергей Борщ @ Dec 28 2010, 20:56) *
Какая разница? Массив тоже может состоять из структур.
Разница проявляется при вычислении значения указателя. Массив структур формально ничем не отличается от массива байт или слов - в массиве все элементы одинаковые по размеру. Если бы массивы и структуры были суть одно и то же, но какой смысл было вводить новые абстракции? wink.gif
GetSmart
Цитата(Сергей Борщ @ Dec 28 2010, 20:56) *
Найдите мне теперь любое действие, которое я могу выполнить с ptr и не могу выполнить с array. Или наоборот.

Если бы имя массива было эквивалентно адресу на его первый элемент, то компилятор не ругался бы на это

Код
u08 massiv[100];
u08 *ptr = massiv;


однако компилятор ругается и требует так
Код
u08 massiv[100];
u08 *ptr = &massiv[0];


========
upd
Проверил, ИАР не ругается.
ViKo
Цитата(GetSmart @ Dec 28 2010, 19:43) *
однако компилятор ругается и требует так

Теоретически, компилятор ругаться не должен. Потому что в книжках написано, что имя массива есть адрес его первого элемента. Так же, как имя функции есть адрес входа в эту функцию.
Сергей Борщ прав, когда говорит, что операции с ptr и array одинаково допустимы. Разница в том, как это будет реализовано при обработке всего массива.
GetSmart
В книжках так же пишут, что детей находят в капусте sm.gif
ViKo
Цитата(GetSmart @ Dec 28 2010, 20:21) *
В книжках так же пишут, что детей находят в капусте sm.gif

Ну, вот пример специально для вас. Keil, STM32.
Код
  static const uint8_t Digit[10] = {'0','1','2','3','4','5','6','7','8','9'};
  const uint8_t *pDig = Digit;
  for (uint32_t i=10; i--; ) GPIOA->ODR = *(pDig++);

вот часть листинга после компиляции
Код
;;;202      static const uint8_t Digit[10] = {'0','1','2','3','4','5','6','7','8','9'};
;;;203      const uint8_t *pDig = Digit;
000092  486d              LDR      r0,|L1.584|
;;;204      for (uint32_t i=10; i--; ) GPIOA->ODR = *(pDig++);
000094  210a              MOVS     r1,#0xa
000096  4b6d              LDR      r3,|L1.588|
000098  e003              B        |L1.162|
                  |L1.154|
00009a  f8102b01          LDRB     r2,[r0],#1
00009e  f8c3280c          STR      r2,[r3,#0x80c]
                  |L1.162|
0000a2  1e49              SUBS     r1,r1,#1
0000a4  d2f9              BCS      |L1.154|

Я удивляюсь, что вы подвергаете сомнению азбучные истины sm.gif О, заметил, вы уже исправились sm.gif
XVR
По поводу массив/указатель уже где то тут выясняли. Для компилятора они НЕ ЯВЛЯЮТСЯ одинаковыми сущностями. Пример:
1й С файл
Код
char msg[]="Hello, world!";

1й С файл
Код
extern char* msg;
main()
{
  puts(msg);
}
Скомпилите, слинкуйте, запустите и наслаждайтесь sm.gif
Сергей Борщ
QUOTE (rezident @ Dec 28 2010, 18:10) *
Разница проявляется при вычислении значения указателя. Массив структур формально ничем не отличается от массива байт или слов - в массиве все элементы одинаковые по размеру. Если бы массивы и структуры были суть одно и то же, но какой смысл было вводить новые абстракции? wink.gif
Я вас не понимаю. В массиве все элементы одинаковые по размеру. Бесспорно. Но точно также одинаковы по размеру и *ptr и *(ptr + 1) и *(ptr + n). Указатель указывает на данные совершенно определенного и всегда одного и того же типа типа независимо от того, куда именно он указывает. Более того, увеличивая указатель на 1 содержащийся в нем адрес увеличивается ровно на столько же, насколько отличаются адреса соседних элементов массива из данных того же типа. И в обоих случаях с учетом выравнивания. Нету разницы в вычислении адреса. Или приведите пример.

QUOTE (XVR @ Dec 28 2010, 21:51) *
Для компилятора они НЕ ЯВЛЯЮТСЯ одинаковыми сущностями. Пример:
По поводу объявления/инициализации была оговорка.
XVR
Если подходить строго, то с массивом в С определены всего 2 операции - sizeof от него, и автоматическое преобразование имени массива в указатель на его нулевой элемент. ВСЕ ОСТАЛЬНЫЕ операции на самом деле производятся именно с этим указателем.


Цитата(Сергей Борщ @ Dec 28 2010, 23:14) *
По поводу объявления/инициализации была оговорка.
В случает ТС разница между *** и **[] будет катастрофическая

Сергей Борщ
QUOTE (XVR @ Dec 28 2010, 22:22) *
ВСЕ ОСТАЛЬНЫЕ операции на самом деле производятся именно с этим указателем.
Совершенно верно. Вот цитата из стандарта, желающие могут поспорить с ним:
QUOTE
6.3.2.1 Lvalues, arrays, and function designators
3. Except when it is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue.
ViKo
Решил сравнить адресную и индексную арифметику на приведенном выше своем примере.
Код
;;;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 (uint32_t i=10; i; i--) GPIOA->ODR = *(pDig++);
000094  4a70              LDR      r2,|L1.600|
000096  210a              MOVS     r1,#0xa
                  |L1.152|
000098  f8103b01          LDRB     r3,[r0],#1
00009c  f8c2380c          STR      r3,[r2,#0x80c]
0000a0  1e49              SUBS     r1,r1,#1
0000a2  d1f9              BNE      |L1.152|
0000a4  496b              LDR      r1,|L1.596|
;;;205      for (int32_t j=9; j>=0; j--) GPIOA->ODR = Digit[j];
0000a6  2009              MOVS     r0,#9
                  |L1.168|
0000a8  5c0b              LDRB     r3,[r1,r0]
0000aa  f8c2380c          STR      r3,[r2,#0x80c]
0000ae  1e40              SUBS     r0,r0,#1
0000b0  d5fa              BPL      |L1.168|

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

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

То, что показал - лучшее. Прошелся по всем вариантам оптимизации. На мой взгляд, компилятор не должен быть настолько умным, как вы говорите. sm.gif
Еще попробовал заменить тип переменных в массиве на uint16_t и uint32_t. В первом случае коды для адресной и индексной арифметик сравнялись, а во втором индексная арифметика опять вырвалась вперед.
Сергей Борщ
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];
ViKo
Цитата(Сергей Борщ @ 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.
GetSmart
Цитата(ViKo @ Dec 29 2010, 01:55) *
Результат слегка обескуражил. Обращение к элементу массива с помощью индекса занимает меньше байтов.
Особенность системы команд ARM.

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

Цитата(XVR @ Dec 29 2010, 01:23) *
В случает ТС разница между *** и **[] будет катастрофическая

Что такое ТС? "В случает ТС"
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.