Перейти к содержанию
    

Научите как правильно передавать массив в функцию

4 минуты назад, MrBearManul сказал:

Я правильно вас понимаю, что если вынести объявление массива arr[10] из функции func() и сделать его глобальным, то sizeof(arr) вернёт уже размер указателя?

Если вынести объявление массива arr[10] из функции func() и сделать его глобальным, то sizeof(arr) вернёт уже размер массива arr, т.е. размер одного элемента массива * на количество элементов массива.

Если массив arr[10] объявлен в функции func(), то sizeof(arr) вернёт размер указателя на элементов массива arr.

Большие по размерам массивы не стоит объявлять внутри функции, так как локальные объекты хранятся на стеке, а размер стека не такой большой. Если надо объявить большой массив, то это будет глобальный объект или через динамическое выделение памяти в куче malloc для языка С. Работа с глобальными объектами требует меньше времени CPU, чем с объектами в куче, но нет такой гибкости как у объектов в куче. Это небольшое отступление от темы, так как рано или поздно Вы попробуете объявить большой массив на стеке. 

15 минут назад, MrBearManul сказал:

Я правильно вас понимаю, что если вынести объявление массива arr[10] из функции func() и сделать его глобальным, то sizeof(arr) вернёт уже размер указателя?

А разве вы не то же самое говорили, цитирую ниже:

Так почему же пример уважаемого @Arlleex вернул 10, а не 4?

Пример  @Arlleex вернул 10, а не 4?

Проверил, тут я не прав. Вернул 10 так как sizeof применен к имени массива, хоть этот объект объявлен на стеке. Тут есть маленький нюанс, что надо передавать именно имя исходного массива в функцию sizeof. В случае передачи массива по указателю будет возвращен размер указателя.

Есть примеры использования sizeof:

https://www.geeksforgeeks.org/sizeof-operator-c/

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

13 минут назад, uk_denis сказал:

Если массив arr[10] объявлен в функции func(), то sizeof(arr) вернёт размер указателя на элементов массива arr.

Еще раз перечитайте мое сообщение с примером кода.

15 минут назад, uk_denis сказал:

так как рано или поздно Вы попробуете объявить большой массив на стеке...

Рано или поздно тот, кто сидит между стулом и монитором, начнет включать голову:wink:

15 минут назад, uk_denis сказал:

Работа с глобальными объектами требует меньше времени CPU, чем с объектами в куче...

Это еще с чего бы? На какой архитектуре?

17 минут назад, uk_denis сказал:

...передавать именно имя исходного массива в функцию sizeof...

sizeof() - это операция, а не функция.
Это в порядке "докапаться":biggrin:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

29 минут назад, uk_denis сказал:

Большие по размерам массивы не стоит объявлять внутри функции, так как локальные объекты хранятся на стеке, а размер стека не такой большой

Заблуждение. Можно сделать так

void foo() {
  static type_t my_array[MY_ARRAY_SIZE];
}

Массив объявлен внутри функции. А размещён будет не на стэке.

29 минут назад, uk_denis сказал:

Это небольшое отступление от темы, так как рано или поздно Вы попробуете объявить большой массив на стеке. 

Простите за прямоту, но чтобы не было недомолвок: ваши познания языка Си пока очень слабы. Этот вывод я делаю не по одному вашему высказыванию, а по нескольким. По-крайней мере в тех областях, которые вы озвучили. Подучите его, тогда и поговорим)

29 минут назад, uk_denis сказал:

Работа с глобальными объектами требует меньше времени CPU, чем с объектами в куче, но нет такой гибкости как у объектов в куче.

Доказательства?:blum:

29 минут назад, uk_denis сказал:

или через динамическое выделение памяти в куче malloc для языка С.

Которое может оказаться совершенно неприемлимым для встраиваемых систем.

29 минут назад, uk_denis сказал:

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

Не-а, это не так) Он может быть и локальным, с указанием линковщику разместить его в секции .data или .bss

Изменено пользователем MrBearManul

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

8 минут назад, Arlleex сказал:
25 минут назад, uk_denis сказал:

Работа с глобальными объектами требует меньше времени CPU, чем с объектами в куче...

Это еще с чего бы? На какой архитектуре?

При выделении объекта из кучи необходим вызов malloc, на который тратится время. При освобождении объекта из кучи надо вызвать free, на что тоже тратиться время. 

При работе с глобальным объектом во время выполнения программы (runtime) время не тратиться на инициализацию и освобождение памяти, так как объект размещен компилятор по заданному адресе линковщиком.

Также возможна проблема фрагментации кучи.

При работе с указателями возможен ряд ошибок, поэтому в частности в стандарте MISRA C не используются указатели и выделение памяти из кучи для безопасности, переносимости и надежности программ для встраиваемых систем.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

8 минут назад, uk_denis сказал:

...если размер элемента массива не равен единице... необходимо количество элементов массива умножить на размер элемента массива
...
memset(my_array, 0xFF, sizeof(my_array[0])*sizeof(my_array));

Что-то опять как-то мимо. С текстом правильно, с кодом - беда.

9 минут назад, uk_denis сказал:

...sizeof возвращает количество элементов массива применительно к имени массива...

sizeof() возвращает объем памяти, занимаемый объектом, в эквиваленте элементов char.
А char, насколько мне известно, не на всех архитектурах равен 8 битам. В каких-то DSP, вроде, 16 бит.
Но это уже лирическое отступление.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

10 минут назад, MrBearManul сказал:

void foo() {
  static type_t my_array[MY_ARRAY_SIZE];
}

Массив объявлен внутри функции. А размещён будет не на стэке.

Массив находится в глобальной области памяти, так как он объявлен через static.   Поэтому он размещается не на стеке функции. 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 минуты назад, uk_denis сказал:

При выделении объекта из кучи необходим вызов malloc, на который тратится время...

А, Вы про это... Я думал, что Вы о работе с уже выделенной памятью.

4 минуты назад, uk_denis сказал:

в стандарте MISRA C не используются указатели...

А можно прям носом меня ткнуть в место, где это написано?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Массив находится в глобальной области памяти, так как он объявлен через static.   Поэтому он размещается не на стеке функции. 

Насколько я помню, вы утверждали следующее, т.е. дословно: "внутри функции".

44 минуты назад, uk_denis сказал:

Большие по размерам массивы не стоит объявлять внутри функции, так как локальные объекты хранятся на стеке, а размер стека не такой большой.

10 минут назад, uk_denis сказал:

При выделении объекта из кучи необходим вызов malloc, на который тратится время

А во встраиваемых системах нередко не используют штатный "кучер" (ну менеджер кучи). Поэтому он может работать довольно шустро, и время на выделение уже будет довольно малым по сравнению со временем работы с данными. И вообще, почему вы вдруг заговорили о куче? Её вроде никто не упоминал)

13 минут назад, uk_denis сказал:

так как объект размещен компилятор по заданному адресе линковщиком

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 часа назад, Arlleex сказал:

А можно прям носом меня ткнуть в место, где это написано?

MISRA-C 2004 Guidelines for the use of the C language in critical systems

Rule 20.4 (required): Dynamic heap memory allcocation shall not be used.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

4 часа назад, Arlleex сказал:
4 часа назад, uk_denis сказал:

в стандарте MISRA C не используются указатели...

А можно прям носом меня ткнуть в место, где это написано?

21 минуту назад, uk_denis сказал:

Rule 20.4 (required): Dynamic heap memory allcocation shall not be used.

Странный диалог. До свидания:wink::biggrin:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

4 часа назад, uk_denis сказал:

Dynamic heap memory allcocation shall not be used.

Не следует использовать динамическое выделение памяти в куче.

Вы же утверждали, что

8 часов назад, uk_denis сказал:

в стандарте MISRA C не используются указатели

Но это всё отступление от темы.

А вот это очень показательный ваш код:

void func1();

void func2();

 

#define SIZE_BUF 50

 

uint8_t my_array[SIZE_BUF];

 

void main()
{
  func1(my_array);
}

 

void func1()
{
  memset(my_array, 0x00, sizeof(my_array[0])*sizeof(my_array));
  func2();
}

 

void func2()
{
  memset(my_array, 0xFF, sizeof(my_array[0])*sizeof(my_array));
}

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

Ничего странного в func1() не видите? Несоответствие между объявлением и использованием?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

10 часов назад, uk_denis сказал:

sizeof возвращает количество элементов массива применительно к имени массива

Сами придумали? Если нет - приведите ссылку на источник этих знаний. Цитата из стандарта подойдёт.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот они, коршуны налетели:biggrin:

P.S. @Darth Vader, код тот даже скомпилится:wink: Но есть нюансы.
Пустые скобки функции в Си сообщают, что та принимает неопределенное кол-во аргументов неопределенных типов.
В C++, вроде как, пустые скобки говорят, что аргументов функция не принимает. Поэтому в Си лучше писать [type] func(void).
Другое дело, что безопасность такого кода напрямую будет зависеть от принятого соглашения вызовов компилятора (кто чистит стек).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

23 hours ago, uk_denis said:

Если вынести объявление массива arr[10] из функции func() и сделать его глобальным, то sizeof(arr) вернёт уже размер массива arr, т.е. размер одного элемента массива * на количество элементов массива.

Если массив arr[10] объявлен в функции func(), то sizeof(arr) вернёт размер указателя на элементов массива arr.

Большие по размерам массивы не стоит объявлять внутри функции, так как локальные объекты хранятся на стеке, а размер стека не такой большой. Если надо объявить большой массив, то это будет глобальный объект или через динамическое выделение памяти в куче malloc для языка С. Работа с глобальными объектами требует меньше времени CPU, чем с объектами в куче, но нет такой гибкости как у объектов в куче. Это небольшое отступление от темы, так как рано или поздно Вы попробуете объявить большой массив на стеке. 

Пример  @Arlleex вернул 10, а не 4?

Проверил, тут я не прав. Вернул 10 так как sizeof применен к имени массива, хоть этот объект объявлен на стеке. Тут есть маленький нюанс, что надо передавать именно имя исходного массива в функцию sizeof. В случае передачи массива по указателю будет возвращен размер указателя.

Есть примеры использования sizeof:

https://www.geeksforgeeks.org/sizeof-operator-c/

Вот поэтому более универсальным способом будет заполнение массива тем способом, который я ранее предложил. Если использовать просто sizeof(arr), то при переобъявлении массива из локального в глобальный можно забыть про его заполнение в какой-нибудь функции. Хотя я сам тонкости в цитате не знал, но заполняю массив таким способом из интуитивных соображений как более универсальным и однозначным. 

memset(buf_2, 0xFF, sizeof(uint8_t) * SIZE_BUF);

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...