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

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

STM32. STM32CubeIde.

Есть глобальный массив. Передаю указатель на него в функцию. Код прописанный в функции меняет значения элементов массива. Затем из этой функции мне необходимо вызвать еще одну, также с указанием данного массива. Вот тут не получается. Вторая функция уже не модифицирует элементы того самого глобального массива.

 

void func1(uint8_t *buf_1);
void func2(uint8_t *buf_2);

uint8_t my_array[50];

void main
{
  func1(my_array);
}

void func1(uint8_t *buf_1)
{
  memset(buf_1, 0x00, sizeof(buf_1)); // Здесь все нормально, все элементы my_array устанавливаются в 0
  func2(buf_1);
}

void func2(uint8_t *buf_2)
{
  memset(buf_2, 0xFF, sizeof(buf_2)); // Здесь только первые 4 элемента my_array устанавливаются в FF, остальные не модифицируются
}

 

Также компилятор выдает warning: argument to 'sizeof' in 'memset' call is the same expression as the destination; did you mean to provide an explicit length? [-Wsizeof-pointer-memaccess]
 
Понимаю, что как-то ошибочно ссылаюсь на массив при вызове второй функции, но не понимаю как сделать правильно.

 

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


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

2 minutes ago, Dec_NN said:

Здесь все нормально, все элементы my_array устанавливаются в 0

Нет, не нормально. sizeof(buf_1) возвращает размер указателя, а не массива.

А элементы и так инициализированы в 0.

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


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

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


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

 

void main
{
  func1(my_array, sizeof(my_array));
}

 

void func1(uint8_t *buf_1,  uint32_t size)
{
  memset(buf_1, 0x00, size); // Здесь все нормально, все элементы my_array устанавливаются в 0
  func2(buf_1, 4);
}

void func2(uint8_t *buf_2,  uint32_t size)
{
  memset(buf_2, 0xFF, size); // Здесь только первые 4 элемента my_array устанавливаются в FF, остальные не модифицируются
}

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


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

37 minutes ago, Dec_NN said:
35 minutes ago, aaarrr said:

Нет, не нормально. sizeof(buf_1) возвращает размер указателя, а не массива.

А элементы и так инициализированы в 0.

Действительно. Вы правы.

 

25 minutes ago, HardEgor said:

 

void main
{
  func1(my_array, sizeof(my_array));
}

 

void func1(uint8_t *buf_1,  uint32_t size)
{
  memset(buf_1, 0x00, size); // Здесь все нормально, все элементы my_array устанавливаются в 0
  func2(buf_1, 4);
}

void func2(uint8_t *buf_2,  uint32_t size)
{
  memset(buf_2, 0xFF, size); // Здесь только первые 4 элемента my_array устанавливаются в FF, остальные не модифицируются
}

Огромное спасибо. Теперь все понял. Проблема не в передаче указателя, а в работе функции sizeof.

func2(buf_1, 4) из вашего примера заменил на func2(buf_1, size);

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


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

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

Проблема не в передаче указателя, а в работе функции sizeof.

Проблема в том, что вы изначально не поняли, что передавая функции указатель на объект, ей надо передать и количество этих объектов, если хотите работать с массивом этих объектов. Откуда функция узнает количество элементов в массиве, имея только указатель на один из его элементов? Код в теле функции не отличает указатель на объект от указателя на массив объектов. Для него они абсолютно одинаковы. Не просто так стандартные функции memset, memcpy, memcmp имеют параметр - размер объекта в байтах.

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


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

Я сделал бы так:
 

void func1(uint8_t *buf_1);
void func2(uint8_t *buf_2);

#define SIZE_BUF 50

uint8_t my_array[SIZE_BUF];

void main
{
  func1(my_array);
}

void func1(uint8_t *buf_1)
{
  memset(buf_1, 0x00, sizeof(uint8_t) * SIZE_BUF);
  func2(buf_1);
}

void func2(uint8_t *buf_2)
{
  memset(buf_2, 0xFF, sizeof(uint8_t) * SIZE_BUF);
}

Передача нескольких параметров в функцию - это дурной тон. В данном случае только два, что ещё терпимо. А если их несколько, то лучше передать указатель на структуру.

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


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

19 минут назад, ДЕЙЛ сказал:

Передача нескольких параметров в функцию - это дурной тон.

А пруфы будут?

Цитата

В данном случае только два, что ещё терпимо.

Передаю 4, уже не терпимо?:crazy:

Цитата

А если их несколько, то лучше передать указатель на структуру.

Чем лучше? Синтаксически - да. По быстроте ~нет.

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


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

4 minutes ago, Arlleex said:

А пруфы будут?

Передаю 4, уже не терпимо?:crazy:

Чем лучше? Синтаксически - да. По быстроте ~нет.

Параметр передаётся обычно через регистр процессора, число которых ограничено. Если параметров будет слишком много, то передаваться они будут через обычную память, что замедлит выполнение программы. Ещё и размер памяти программы увеличивается при неоптимальном коде.

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


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

1 минуту назад, ДЕЙЛ сказал:

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

А Ваша структура, указатель на которую Вы хотите потом передать аргументом, память не требует?

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


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

4 minutes ago, Arlleex said:

А Ваша структура, указатель на которую Вы хотите потом передать аргументом, память не требует?

Есть структура из 100 параметров.

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

При вызове функции с передачей указателя никакого дополнительного копирования не потребуется.

 

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

 

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


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

3 минуты назад, ДЕЙЛ сказал:

При вызове функции с передачей указателя никакого дополнительного копирования не потребуется.

Это, конечно, очевидно, но это в корне меняет суть: теперь в вызванной функции я могу изменить эти самые параметры, а значит, локальными они уже не являются.

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


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

44 minutes ago, ДЕЙЛ said:

#define SIZE_BUF 50

Это совсем дурной тон - передавать в функцию указатель на массив, размер которого где-то задефайнен.

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


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

Сколько способов, столько и мнений. В каждой ситуации идеальным будет компромиссное решение. Это как написать "Hello world" разными способами.

 

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


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

1 час назад, ДЕЙЛ сказал:

memset(buf_1, 0x00, sizeof(uint8_t) * SIZE_BUF);

А чего не так

memset(buf_1, 0x00, sizeof(my_array));

???

50 минут назад, ДЕЙЛ сказал:

то замедлит выполнение программы.

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

38 минут назад, ДЕЙЛ сказал:

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

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

22 минуты назад, ДЕЙЛ сказал:

Это как написать "Hello world" разными способами.

Правда реальные программы координально отличаются от "Hello World". В общем, изучайте стандарты языка. Тогда и говорить дальше можно будет)

50 минут назад, ДЕЙЛ сказал:

Параметр передаётся обычно через регистр процессора, число которых ограничено.

А если компилятор заинлайнит функцию?

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

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


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

11 minutes ago, MrBearManul said:

А чего не так


memset(buf_1, 0x00, sizeof(my_array));

???

Лучше перебдеть и накодить под самый тупой компилятор. my_array может восприняться как указатель на начало массива.

11 minutes ago, MrBearManul said:

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

Простите, но вы разарботчиков компиляторов совсем не уважаете? Оптимизаторы нынче весьма лихие, и копирование может не понадобится. Однако, если локальная переменная, а именно таковой является аргумент функции без ссылки, меняется, то без копирования не обойтись.

Правда реальные программы координально отличаются от "Hello World". 

если компилятор заинлайнит функцию?

Упрощение жизни компилятору кашу не испортит.  Компиляторы не боги и тоже делают ошибки, для обхода которых иногда приходится менять код алгоритма.

12 minutes ago, MrBearManul said:

 В общем, изучайте стандарты языка. Тогда и говорить дальше можно будет)

Пока только 6 лет непрерывного кодинга на Си, но обязательно изучу язык!

Изменено пользователем ДЕЙЛ

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


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

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

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

Гость
Ответить в этой теме...

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

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

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

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

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

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