Вопрос по массиву
-
maksimdag0
- Прорезались зубы
- Сообщения: 225
- Зарегистрирован: Чт апр 08, 2021 09:46:48
Вопрос по массиву
Все добрый вечер!
Я столкнулся с таким случаем: передаю массив в функцию test, через указатель (см. фото 1). В теле этой функции я передаю массив другой функции - big, но передаю по одному элементу таким образом - каждый элемент массива преравниваю к первому элементу и передаю его в функцию big, НО это не работает, почему? Почему нельзя записать в первый элемент массива его любой другой элемент? (см. фото 2)
Я отслеживал под отладкой это процесс, и выявил что никакое значение не записывается в первый элемент массива, и даже больше значение arr[i] не изменялось вообще, хотя переменная "i" изменялась. подскажите пожалуйста, что я не знаю, почему так происходит?
Я столкнулся с таким случаем: передаю массив в функцию test, через указатель (см. фото 1). В теле этой функции я передаю массив другой функции - big, но передаю по одному элементу таким образом - каждый элемент массива преравниваю к первому элементу и передаю его в функцию big, НО это не работает, почему? Почему нельзя записать в первый элемент массива его любой другой элемент? (см. фото 2)
Я отслеживал под отладкой это процесс, и выявил что никакое значение не записывается в первый элемент массива, и даже больше значение arr[i] не изменялось вообще, хотя переменная "i" изменялась. подскажите пожалуйста, что я не знаю, почему так происходит?
- Вложения
-
- Screenshot_2.png
- (3.07 КБ) 115 скачиваний
-
- Screenshot_1.png
- (1.44 КБ) 96 скачиваний
Re: Вопрос по массиву
Ну так передайте указатель. А еще лучше почитайте про указатели.
- VladislavS
- Собутыльник Кота
- Сообщения: 2562
- Зарегистрирован: Вт май 01, 2018 19:44:47
Re: Вопрос по массиву
Как объявлен arr предлагается угадать?
Re: Вопрос по массиву
Там у вас всё чето сильно позапутано всё, неясна конечная цель и что для чего делается. Если нулевому элементу входного массива присваивается значение из неизвестно откуда взявшегося массива, а потом этот элемент передается в другую функцию, то можно всю эту цепочку сократить, убрав лишние действия:
Re: Вопрос по массиву
отключите оптимизацию
компилятор, скорее всего, просто вас не понял
компилятор, скорее всего, просто вас не понял
-
maksimdag0
- Прорезались зубы
- Сообщения: 225
- Зарегистрирован: Чт апр 08, 2021 09:46:48
Re: Вопрос по массиву
Я ошибся там не "arr", а arr_2[i]korsaj писал(а):Ну так передайте указатель. А еще лучше почитайте про указатели.
- VladislavS
- Собутыльник Кота
- Сообщения: 2562
- Зарегистрирован: Вт май 01, 2018 19:44:47
Re: Вопрос по массиву
maksimdag0, вам надо переосмыслить как компилятор "видит" код, который вы пишете. Для него важны только volatile сущности, со всем остальным он может обходиться как хочет. Вот взять, например, компилятор IAR и ваш код с пустой функцией big(). Смотрите что получитсяКомпилятор посчитал, что это всё что делает программа. Никаких циклов и передачи параметров в функцию нет.
Теперь введём в функцию big() volatile сущность.Мы можем видеть, что добавилось полезное действие - последовательный вывод в GPIOA->IDR элементов массива.
Но это ещё не всё. Немного поможем компилятору, избавим его от глупого кода.Лучше, нет лишних действий, но всё равно что-то не то. Потому что компилятор пока что не знает что мы ему в функцию передаём, это просто листинг тела функции.
Попробуем эту функцию вызвать c константными данными.Ровно то что и задумано, в GPIOA->IDR последовательно записано 1,2,3 без всяких массивов и циклов вообще. Потому что GPIOA->IDR это volatile сущность и только она в этой программе важна для компилятора. Ну и для программиста, конечно, тоже, если он хочет писать привильные программы. Смотрите, что будет, если big() не будет воздействовать на volatile сущности.Всё "почикано" под корень. Вот, это вам пища для размышлений. С опытом должно прийти понимание того что же на самом деле делает написанный вами код. Это основы языка программирования, которым почему-то нигде не учат.
PS: Это я ещё взял компилятор, который бережно работает с доступом по указателю. GCC бы всё это "вычистил под ноль" ещё на первом шаге.
Код: Выделить всё
void big(int x) { }
void test (int *arr_2)
{
for(int i=0; i<3; i++)
{
arr_2[0]=arr_2[i];
big(arr_2[0]);
LDR R1,[R0, #+4] // R1 = arr_2[1]
STR R1,[R0, #+0] // arr_2[0] = R1
LDR R2,[R0, #+8] // R1 = arr_2[2]
STR R2,[R0, #+0] // arr_2[0] = R1
}
}
BX LR Теперь введём в функцию big() volatile сущность.
Код: Выделить всё
void big(int x) { GPIOA->IDR=x; }
void test (int *arr_2)
{
for(int i=0; i<3; i++)
LDR.N R1,??DataTable2 // R1 = &GPIOA->IDR
{
arr_2[0]=arr_2[i];
big(arr_2[0]);
LDR R2,[R0, #+0] // R2 = arr_2[0]
STR R2,[R1, #+0] // GPIOA->IDR = R2
LDR R2,[R0, #+4] // R2 = arr_2[1]
STR R2,[R0, #+0] // arr_2[0] = R2
STR R2,[R1, #+0] // GPIOA->IDR = R2
LDR R2,[R0, #+8] // R2 = arr_2[2]
STR R2,[R0, #+0] // arr_2[0] = R2
STR R2,[R1, #+0] // GPIOA->IDR = R2
}
}
BX LR Но это ещё не всё. Немного поможем компилятору, избавим его от глупого кода.
Код: Выделить всё
void big(int x) { GPIOA->IDR=x; }
void test (int *arr_2)
{
for(int i=0; i<3; i++) big(arr_2[i]);
LDR.N R1,??DataTable2 // R1 = &GPIOA->IDR
LDR R2,[R0, #+0] // R2 = arr_2[0]
STR R2,[R1, #+0] // GPIOA->IDR = R2
LDR R2,[R0, #+4] // R2 = arr_1[1]
STR R2,[R1, #+0] // GPIOA->IDR = R2
LDR R2,[R0, #+8] // arr_1[0] = R2
STR R2,[R1, #+0] // GPIOA->IDR = R2
}
BX LR Попробуем эту функцию вызвать c константными данными.
Код: Выделить всё
void big(int x) { GPIOA->IDR=x; }
const int arr_1[3] = { 1,2,3 };
int main()
{
test((int *)arr_1);
LDR.N R0,??DataTable2 // R0 = &GPIOA->IDR
MOVS R1,#+1
STR R1,[R0, #+0] // GPIOA->IDR = 1;
MOVS R2,#+2
STR R2,[R0, #+0] // GPIOA->IDR = 2;
MOVS R3,#+3
STR R3,[R0, #+0] // GPIOA->IDR = 3;
}Код: Выделить всё
void big(int x) { }
const int arr_1[3] = { 1,2,3 };
void test (int *arr_2)
{
for(int i=0; i<3; i++) big(arr_2[i]);
}
int main()
{
test((int *)arr_1);
for(;;);
??main_0:
B.N ??main_0
}PS: Это я ещё взял компилятор, который бережно работает с доступом по указателю. GCC бы всё это "вычистил под ноль" ещё на первом шаге.
-
maksimdag0
- Прорезались зубы
- Сообщения: 225
- Зарегистрирован: Чт апр 08, 2021 09:46:48
Re: Вопрос по массиву
Большое спасибо, буду разбираться, пока сложно это понять)VladislavS писал(а):maksimdag0, вам надо переосмыслить как компилятор "видит" код, который вы пишете. Для него важны только volatile сущности, со всем остальным он может обходиться как хочет. Вот взять, например, компилятор IAR и ваш код с пустой функцией big(). Смотрите что получитсяКомпилятор посчитал, что это всё что делает программа. Никаких циклов и передачи параметров в функцию нет.Код: Выделить всё
void big(int x) { }
void test (int *arr_2)
{
for(int i=0; i<3; i++)
{
arr_2[0]=arr_2[i];
big(arr_2[0]);
LDR R1,[R0, #+4] // R1 = arr_2[1]
STR R1,[R0, #+0] // arr_2[0] = R1
LDR R2,[R0, #+8] // R1 = arr_2[2]
STR R2,[R0, #+0] // arr_2[0] = R1
}
}
BX LR
Теперь введём в функцию big() volatile сущность.Мы можем видеть, что добавилось полезное действие - последовательный вывод в GPIOA->IDR элементов массива.Код: Выделить всё
void big(int x) { GPIOA->IDR=x; }
void test (int *arr_2)
{
for(int i=0; i<3; i++)
LDR.N R1,??DataTable2 // R1 = &GPIOA->IDR
{
arr_2[0]=arr_2[i];
big(arr_2[0]);
LDR R2,[R0, #+0] // R2 = arr_2[0]
STR R2,[R1, #+0] // GPIOA->IDR = R2
LDR R2,[R0, #+4] // R2 = arr_2[1]
STR R2,[R0, #+0] // arr_2[0] = R2
STR R2,[R1, #+0] // GPIOA->IDR = R2
LDR R2,[R0, #+8] // R2 = arr_2[2]
STR R2,[R0, #+0] // arr_2[0] = R2
STR R2,[R1, #+0] // GPIOA->IDR = R2
}
}
BX LR
Но это ещё не всё. Немного поможем компилятору, избавим его от глупого кода.Лучше, нет лишних действий, но всё равно что-то не то. Потому что компилятор пока что не знает что мы ему в функцию передаём, это просто листинг тела функции.Код: Выделить всё
void big(int x) { GPIOA->IDR=x; }
void test (int *arr_2)
{
for(int i=0; i<3; i++) big(arr_2[i]);
LDR.N R1,??DataTable2 // R1 = &GPIOA->IDR
LDR R2,[R0, #+0] // R2 = arr_2[0]
STR R2,[R1, #+0] // GPIOA->IDR = R2
LDR R2,[R0, #+4] // R2 = arr_1[1]
STR R2,[R1, #+0] // GPIOA->IDR = R2
LDR R2,[R0, #+8] // arr_1[0] = R2
STR R2,[R1, #+0] // GPIOA->IDR = R2
}
BX LR
Попробуем эту функцию вызвать c константными данными.Ровно то что и задумано, в GPIOA->IDR последовательно записано 1,2,3 без всяких массивов и циклов вообще. Потому что GPIOA->IDR это volatile сущность и только она в этой программе важна для компилятора. Ну и для программиста, конечно, тоже, если он хочет писать привильные программы. Смотрите, что будет, если big() не будет воздействовать на volatile сущности.Код: Выделить всё
void big(int x) { GPIOA->IDR=x; }
const int arr_1[3] = { 1,2,3 };
int main()
{
test((int *)arr_1);
LDR.N R0,??DataTable2 // R0 = &GPIOA->IDR
MOVS R1,#+1
STR R1,[R0, #+0] // GPIOA->IDR = 1;
MOVS R2,#+2
STR R2,[R0, #+0] // GPIOA->IDR = 2;
MOVS R3,#+3
STR R3,[R0, #+0] // GPIOA->IDR = 3;
}Всё "почикано" под корень. Вот, это вам пища для размышлений. С опытом должно прийти понимание того что же на самом деле делает написанный вами код. Это основы языка программирования, которым почему-то нигде не учат.Код: Выделить всё
void big(int x) { }
const int arr_1[3] = { 1,2,3 };
void test (int *arr_2)
{
for(int i=0; i<3; i++) big(arr_2[i]);
}
int main()
{
test((int *)arr_1);
for(;;);
??main_0:
B.N ??main_0
}
PS: Это я ещё взял компилятор, который бережно работает с доступом по указателю. GCC бы всё это "вычистил под ноль" ещё на первом шаге.
Re: Вопрос по массиву
что сложно?
речь, почему можете не увидеть Ваш код на выходе компиляции.
примерьте ситуацию на себя - Вы будете перетаскивать кирпичи с места на место, если в этом нет ну совершенно никакой потребности?
если цепочка команд не приводит каким-либо практическим результатам - эта цепочка компилятором может быть "забыта". применительно к Вашему массиву - если содержание массива Вы в дальнейшем никак не используете и компилятор это "просматривает" - ну и зачем ему что-то конфигурить для сущности у которой не будет никакого применения: ни применена в дальнейших расчетах, ни выведена "наружу", ни передана в периферию ...
Хотите увидеть абстрактно как может быть скомпилирован Ваш код, отключите оптимизацию - будет оттранслирован "как есть", без учета "а что собственно нужно" и "как это оптимальнее сделать".
в двух стилях вам рассказали
Владислав профессионально и наглядно.
ну и вот, типа на пальцах
речь, почему можете не увидеть Ваш код на выходе компиляции.
примерьте ситуацию на себя - Вы будете перетаскивать кирпичи с места на место, если в этом нет ну совершенно никакой потребности?
если цепочка команд не приводит каким-либо практическим результатам - эта цепочка компилятором может быть "забыта". применительно к Вашему массиву - если содержание массива Вы в дальнейшем никак не используете и компилятор это "просматривает" - ну и зачем ему что-то конфигурить для сущности у которой не будет никакого применения: ни применена в дальнейших расчетах, ни выведена "наружу", ни передана в периферию ...
Хотите увидеть абстрактно как может быть скомпилирован Ваш код, отключите оптимизацию - будет оттранслирован "как есть", без учета "а что собственно нужно" и "как это оптимальнее сделать".
в двух стилях вам рассказали
Владислав профессионально и наглядно.
ну и вот, типа на пальцах