Allregia 0 Posted January 13 · Report post Возник вопрос о передаче параметров в функции, даже несколко вопросов. Вопрос 1. func( int a){..} и func(const int a){..} Я в курсе что это означает, но не могу понять логику - ведь передается не указатель на переменную а создается копия этой переменной. Так какая разница, меняется она внутри функции или нет, если при выходе из функции копия все равно потеряется а исходная переменная останется без именений? Вопрос 2. переменная, массив: float MyArray[1000]; функция: func( float data[1000]); вызываем: func(MyArra) - передается ведь указатель, а не весь массив в стек запихивается? чем тогда это отличается, если аргументм функции явно написать указатель на массив? func(* flat data[1000]) ? а если функция определена как func(const float data[1000]), то комплилятор при этом проверяет, чтоы внтури функции, данные по тому указателюбыли только ReadOnly? Quote Ответить с цитированием Share this post Link to post Share on other sites
MrBearManul 0 Posted January 13 · Report post 6 минут назад, Allregia сказал: Так какая разница, меняется она внутри функции или нет Для ссылок это имеет значение, но не для обычных переменных, делаю вывод, что это наследие былых времён, когда оптимизаторы были не такие мудрые как сейчас. Такое объявление аргумента позволяло бы им "сообразить" что ничего не нужно копировать в стэк при передаче данных, а использовать сразу адрес с данной переменной. Quote Ответить с цитированием Share this post Link to post Share on other sites
rkit 0 Posted January 13 · Report post 15 minutes ago, Allregia said: Так какая разница, меняется она внутри функции или нет, если при выходе из функции копия все равно потеряется а исходная переменная останется без именений? Разница в том, как переменная ведет себя внутри функции. 14 minutes ago, Allregia said: чем тогда это отличается, если аргументм функции явно написать указатель на массив? func(* flat data[1000]) ? Это будет передача перевого значения массива, а не указатель на массив. Quote Ответить с цитированием Share this post Link to post Share on other sites
Allregia 0 Posted January 13 · Report post 48 minutes ago, MrBearManul said: Для ссылок это имеет значение, Для ссылок то понятно - они для того и передаются ссылками. чтобы можно было менять исходный параметр, например чтобы функция могоа возвращать больше одного значения. Quote Ответить с цитированием Share this post Link to post Share on other sites
Darth Vader 0 Posted January 13 · Report post 1 час назад, Allregia сказал: Я в курсе что это означает, но не могу понять логику Это следствие синтаксиса языка. Практического применения не имеет, но не противоречит грамматике языка. Говорит компилятору, чтобы выдавал ошибку при попытке присвоить параметру новое значение в теле функции. Не важно, имеет это какое-то практическое применение или нет. Такое иногда используют, чтобы не плодить лишние локальные переменные. void stupid_delay(int n) { while(n--) __NOP(); } 2 часа назад, Allregia сказал: чем тогда это отличается, если аргументм функции явно написать указатель на массив? func(* flat data[1000]) ? В языке Си нет полноценного встроенного типа данных - массив. Объявление массива: T arr[n]; - это всего лишь описание n последовательно расположенных в памяти объектов типа Т с общим для всех именем arr, обращение к которым возможно через их общее имя и операцию индексирования. В функции массивы всегда передаются по указателю. Объявления void foo(int a[]); void foo(int* a); эквивалентны. В обоих случаях функция принимает аргумент типа int* . И, заметьте, что в обоих случаях она не имеет понятия, что именно ей передают: указатель на начало массива или просто указатель на отдельную переменную. И если это все-таки массив, то количество элементов в нем ёй тоже неизвестно. Quote Ответить с цитированием Share this post Link to post Share on other sites
Allregia 0 Posted January 13 · Report post 2 hours ago, Darth Vader said: В обоих случаях функция принимает аргумент типа int* . И, заметьте, что в обоих случаях она не имеет понятия, что именно ей передают: указатель на начало массива или просто указатель на отдельную переменную. И если это все-таки массив, то количество элементов в нем ёй тоже неизвестно. Зачем тогда пишут не array[] a array[ххх] ? Например: static void fft(const float x[128], creal32_T y[512]) P.S. Я пытаюсь разоброаться, чего нагенерил Матлаб, точнее что им нагенерили наши алгоритмисты.... А он нагенерил такое, что ни в какой стек не влазит.... Quote Ответить с цитированием Share this post Link to post Share on other sites
jcxz 0 Posted January 13 · Report post 46 минут назад, Allregia сказал: Зачем тогда пишут не array[] a array[ххх] ? Для самокомментируемости. Quote Ответить с цитированием Share this post Link to post Share on other sites
MrBearManul 0 Posted January 14 · Report post 5 часов назад, Allregia сказал: А он нагенерил такое, что ни в какой стек не влазит.... Если документы не секретные и не очень длинные, то вам бы их сюда выложить и листинг в придачу. Возможно, это помогло бы помочь вам) Quote Ответить с цитированием Share this post Link to post Share on other sites
Allregia 0 Posted January 14 · Report post Очень длинные, там почти 400 килобайт текста.... Вот пример парочки функций: static void median(const float x[1419], float y[3]) { int j; int k; float xv[473]; int exitg1; int ipiv; int ia; int ib; int ilast; int oldnv; boolean_T checkspeed; boolean_T isslow; boolean_T exitg2; float vref; float vk; float f2; boolean_T guard1 = false; int c; int ngroupsof5; int nlast; for (j = 0; j < 3; j++) { for (k = 0; k < 473; k++) { xv[k] = x[j + k * 3]; } k = 0; do { exitg1 = 0; if (k < 473) { if (rtIsNaNF(xv[k])) { y[j] = rtNaNF; exitg1 = 1; } else { k++; } } else { ipiv = 236; ia = 0; ib = 472; ilast = 472; oldnv = 473; checkspeed = false; isslow = false; exitg2 = false; while ((!exitg2) && (ia + 1 < ib + 1)) { vref = xv[ipiv]; xv[ipiv] = xv[ib]; xv[ib] = vref; ilast = ia; ipiv = -1; for (k = ia + 1; k <= ib; k++) { vk = xv[k - 1]; f2 = xv[k - 1]; if (f2 == vref) { xv[k - 1] = xv[ilast]; xv[ilast] = vk; ipiv++; ilast++; } else { if (f2 < vref) { xv[k - 1] = xv[ilast]; xv[ilast] = vk; ilast++; } } } xv[ib] = xv[ilast]; xv[ilast] = vref; guard1 = false; if (237 <= ilast + 1) { if (237 >= ilast - ipiv) { exitg2 = true; } else { ib = ilast - 1; guard1 = true; } } else { ia = ilast + 1; guard1 = true; } if (guard1) { c = (ib - ia) + 1; if (checkspeed) { isslow = (c > oldnv / 2); oldnv = c; } checkspeed = !checkspeed; if (isslow) { while (c > 1) { ngroupsof5 = c / 5; nlast = c - ngroupsof5 * 5; c = ngroupsof5; for (k = 0; k < ngroupsof5; k++) { ipiv = (ia + k * 5) + 1; ipiv = thirdOfFive(xv, ipiv, ipiv + 4) - 1; ilast = ia + k; vref = xv[ilast]; xv[ilast] = xv[ipiv]; xv[ipiv] = vref; } if (nlast > 0) { ipiv = (ia + ngroupsof5 * 5) + 1; ipiv = thirdOfFive(xv, ipiv, (ipiv + nlast) - 1) - 1; ilast = ia + ngroupsof5; vref = xv[ilast]; xv[ilast] = xv[ipiv]; xv[ipiv] = vref; c = ngroupsof5 + 1; } } } else { if (c >= 3) { ipiv = ia + (c - 1) / 2; if (xv[ia] < xv[ipiv]) { if (xv[ipiv] < xv[ib]) { } else if (xv[ia] < xv[ib]) { ipiv = ib; } else { ipiv = ia; } } else if (xv[ia] < xv[ib]) { ipiv = ia; } else { if (xv[ipiv] < xv[ib]) { ipiv = ib; } } if (ipiv + 1 > ia + 1) { vref = xv[ia]; xv[ia] = xv[ipiv]; xv[ipiv] = vref; } } } ipiv = ia; ilast = ib; } } y[j] = xv[ilast]; exitg1 = 1; } } while (exitg1 == 0); } } static void merge(int idx[257], float x[257], int offset, int np, int nq, int iwork[257], float xwork[257]) { int n_tmp; int iout; int p; int i6; int q; int exitg1; if ((np == 0) || (nq == 0)) { } else { n_tmp = np + nq; for (iout = 0; iout < n_tmp; iout++) { i6 = offset + iout; iwork[iout] = idx[i6]; xwork[iout] = x[i6]; } p = 0; q = np; iout = offset - 1; do { exitg1 = 0; iout++; if (xwork[p] >= xwork[q]) { idx[iout] = iwork[p]; x[iout] = xwork[p]; if (p + 1 < np) { p++; } else { exitg1 = 1; } } else { idx[iout] = iwork[q]; x[iout] = xwork[q]; if (q + 1 < n_tmp) { q++; } else { q = iout - p; for (iout = p + 1; iout <= np; iout++) { i6 = q + iout; idx[i6] = iwork[iout - 1]; x[i6] = xwork[iout - 1]; } exitg1 = 1; } } } while (exitg1 == 0); } } Quote Ответить с цитированием Share this post Link to post Share on other sites
MrBearManul 0 Posted January 14 (edited) · Report post Эта функция и безо всякого аргумента в виде массива кушает прилично: 1. Раз 7 минут назад, Allregia сказал: float xv[473]; // Тут аж целых 2 кБ стэка 2. Два 7 минут назад, Allregia сказал: float vref; float vk; float f2; boolean_T guard1 = false; int c; int ngroupsof5; int nlast; Можно прикинуть сколько стэка требуется, и в скрипте линкера указать нужное количество. Либо выделить стэка максимально много, заполнить его область водяными знаками, и измерить, сколько реально нужно. Edited January 14 by MrBearManul Quote Ответить с цитированием Share this post Link to post Share on other sites
Allregia 0 Posted January 14 · Report post Еще вопрос - если выделить для стека, ну к примеру 16К, но стек растет сверзу, а остальная память заполняется обычно снизу, и медду ними есть "дырка", не исползльзуемое пространство. Т.е. вполне реальна ситуация, когда стек используется бОльшего размера чем ему сказано. Но пока он щанимает только эту "дырку", и не налазит на занятую память - все работает. Так ведь? Придется тогда в самом деле водяными знаками, потому как при выделении стека в большом (почти 1М) банке памяти, где переменными занята пока лишь треть, все работает. А при выделении всего банка в 64К - через некоторое время получам HF. Quote Ответить с цитированием Share this post Link to post Share on other sites
MrBearManul 0 Posted January 14 · Report post 5 минут назад, Allregia сказал: все работает. Так ведь? Да. 5 минут назад, Allregia сказал: Еще вопрос - если выделить для стека, ну к примеру 16К, но стек растет сверзу, Если речь идёт о кортексах (Cortex-M), то есть уловка: стэк размещают в начале ОЗУ. Тогда, если он выйдет за границы, то налезет уже не на дырку, а на область ввода-вывода, например. И вы получите более вероятный хардфолт, что ускорит отлов ошибки. 6 минут назад, Allregia сказал: А при выделении всего банка в 64К - через некоторое время получам HF. Задействуйте MPU, если есть. И если снова речь идёт о Cortex-M3 и выше. Quote Ответить с цитированием Share this post Link to post Share on other sites
Allregia 0 Posted January 14 · Report post 20 minutes ago, MrBearManul said: Если речь идёт о кортексах (Cortex-M), то есть уловка: стэк размещают в начале ОЗУ. Да, М7, точнее STM32H7A3. 21 minutes ago, MrBearManul said: Задействуйте MPU, если есть. Каким образом? Quote Ответить с цитированием Share this post Link to post Share on other sites
MrBearManul 0 Posted January 14 · Report post 29 минут назад, Allregia сказал: Каким образом? Защитите "дырку" от записи. Но это черезчур, я считаю, что можно обойтись водяными знаками или утащить стэк в начало ОЗУ. Quote Ответить с цитированием Share this post Link to post Share on other sites
Allregia 0 Posted January 14 · Report post 1 minute ago, MrBearManul said: утащить стэк в начало ОЗУ. Какого из? Quote Ответить с цитированием Share this post Link to post Share on other sites