Jump to content

    
Allregia

Передача параметров в функции.

Recommended Posts

Возник вопрос о передаче параметров в функции, даже несколко вопросов.

 

Вопрос 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?

 

 

 

 

 

Share this post


Link to post
Share on other sites
6 минут назад, Allregia сказал:

Так какая разница, меняется она внутри функции или нет

Для ссылок это имеет значение, но не для обычных переменных, делаю вывод, что это наследие былых времён, когда оптимизаторы были не такие мудрые как сейчас. Такое объявление аргумента позволяло бы им "сообразить" что ничего не нужно копировать в стэк при передаче данных, а использовать сразу адрес с данной переменной.

Share this post


Link to post
Share on other sites
15 minutes ago, Allregia said:

Так какая разница, меняется она внутри функции или нет, если при выходе из функции копия все равно потеряется а исходная переменная останется без именений?

Разница в том, как переменная ведет себя внутри функции.

 

14 minutes ago, Allregia said:

чем тогда это отличается, если аргументм функции явно написать указатель на массив? func(* flat data[1000]) ?

Это будет передача перевого значения массива, а не указатель на массив.

Share this post


Link to post
Share on other sites
48 minutes ago, MrBearManul said:

Для ссылок это имеет значение,

Для ссылок то понятно - они для того и передаются ссылками. чтобы можно было менять исходный параметр, например чтобы функция могоа возвращать больше одного значения.

 

 

Share this post


Link to post
Share on other sites
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* . И, заметьте, что в обоих случаях она не имеет понятия, что именно ей передают: указатель на начало массива или просто указатель на отдельную переменную. И если это все-таки массив, то количество элементов в нем ёй тоже неизвестно.

Share this post


Link to post
Share on other sites
2 hours ago, Darth Vader said:

В обоих случаях функция принимает аргумент типа int* . И, заметьте, что в обоих случаях она не имеет понятия, что именно ей передают: указатель на начало массива или просто указатель на отдельную переменную. И если это все-таки массив, то количество элементов в нем ёй тоже неизвестно.

Зачем тогда пишут не array[] a array[ххх] ?

 

Например:

static void fft(const float x[128], creal32_T y[512])

 

P.S. Я пытаюсь разоброаться, чего нагенерил Матлаб, точнее что им нагенерили наши алгоритмисты....

А он нагенерил такое, что ни в какой стек не влазит....

Share this post


Link to post
Share on other sites
5 часов назад, Allregia сказал:

А он нагенерил такое, что ни в какой стек не влазит....

Если документы не секретные и не очень длинные, то вам бы их сюда выложить и листинг в придачу. Возможно, это помогло бы помочь вам)

Share this post


Link to post
Share on other sites

Очень длинные, там почти 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);
  }
}
	 
	

 

Share this post


Link to post
Share on other sites

Эта функция и безо всякого аргумента в виде массива кушает прилично:

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 by MrBearManul

Share this post


Link to post
Share on other sites

Еще вопрос - если  выделить для стека, ну к примеру 16К,  но стек растет сверзу, а остальная память заполняется обычно снизу, и медду ними есть "дырка", не исползльзуемое пространство.

Т.е. вполне реальна ситуация, когда стек используется бОльшего размера чем ему сказано. Но пока он щанимает только эту "дырку", и не налазит на занятую память - все работает. Так ведь?

 

Придется тогда в самом деле водяными знаками, потому как при выделении стека в большом (почти 1М) банке памяти, где переменными занята пока лишь треть, все работает. А при выделении всего банка в 64К - через некоторое время получам HF.

 

Share this post


Link to post
Share on other sites
5 минут назад, Allregia сказал:

все работает. Так ведь?

Да.

5 минут назад, Allregia сказал:

Еще вопрос - если  выделить для стека, ну к примеру 16К,  но стек растет сверзу,

Если речь идёт о кортексах (Cortex-M), то есть уловка: стэк размещают в начале ОЗУ. Тогда, если он выйдет за границы, то налезет уже не на дырку, а на область ввода-вывода, например. И вы получите более вероятный хардфолт, что ускорит отлов ошибки.

6 минут назад, Allregia сказал:

А при выделении всего банка в 64К - через некоторое время получам HF.

Задействуйте MPU, если есть. И если снова речь идёт о Cortex-M3 и выше.

Share this post


Link to post
Share on other sites
20 minutes ago, MrBearManul said:

Если речь идёт о кортексах (Cortex-M), то есть уловка: стэк размещают в начале ОЗУ.

Да, М7, точнее STM32H7A3.

 

21 minutes ago, MrBearManul said:

Задействуйте MPU, если есть.

Каким образом?

Share this post


Link to post
Share on other sites
29 минут назад, Allregia сказал:

Каким образом?

Защитите "дырку" от записи. Но это черезчур, я считаю, что можно обойтись водяными знаками или утащить стэк в начало ОЗУ.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.