Jump to content

    
Dec_NN

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

Recommended Posts

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

my_array может восприняться как указатель на начало массива.

Цитата

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

Как-то эти два высказывания не коррелируют друг с другом. :biggrin:

Да и с вздором о:

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

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

тоже. :unknw:

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

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

3 - это "слишком много"? :shok: Может лучше почитать "соглашения о вызовах" вашего компилятора?

Share this post


Link to post
Share on other sites
2 часа назад, ДЕЙЛ сказал:

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

Ну вы, блин, даёте) Новый Год уже начали праздновать?))))

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

Упрощение жизни компилятору кашу не испортит.

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

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

Хотя в делфях по 2 и 3 параметра есть в готовых функциях.

А при чём здесь дельфи? Её под армы нет, а в тем армы обсуждаются...

Share this post


Link to post
Share on other sites

Если у кого-то много параметров передавать нужно- то можно и про стуктуры подумать.

Очень удобно и универсально. И в функцию легко передавать(указатель), и в очередь многозадачки легко засовывать (хоть целиком, хоть только указатель на). Еще и отлаживать просто, и модифицировать такую программу одно удовольствие. Ну и очень понятно выглядит в исходниках.

Share this post


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

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

Ага. Два экрана запихивания в структуру, за которыми теряется собственно вызов функции.

Share this post


Link to post
Share on other sites

Если на плюсах, то можно использовать шаблонную функцию:

template<std::size_t N> void f(int (&arr)[N]) 
{
    cout << "size: " << N << endl;
    for(int i = 0; i < N; ++i)
    {
        cout << arr[i] << endl;
        
    }
}

int a[] = { 1, 2, 3, 4, 5, 6, 7, 8 };

int main()
{
    f(a);
    return(0);
}

Out log:

size: 8
1
2
3
4
5
6
7
8

Но объявление массива должно быть в области видимости, иначе компилятор не сможет вычислить его размер.

Share this post


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

Если на плюсах, то можно использовать шаблонную функцию:

Я делаю две функции, чтобы не раздувать код для каждого размера массива:

void f(int * arr, size_t size)  
{
    cout << "size: " << size << endl;
    for(int i = 0; i < size; ++i)
    {
        cout << arr[i] << endl;
        
    }
}

template<std::size_t N> inline void f(int (&arr)[N])
{
    f(&arr, N);
}

 

Share this post


Link to post
Share on other sites
16 hours ago, Сергей Борщ said:

Ага. Два экрана запихивания в структуру, за которыми теряется собственно вызов функции.

А что, еще кто-то хранит много взаимосвзязанных (используемых вместе) данных не в структурах?

 

Если данные связаны между собой (например, массив и указатели записи-чтения в нем) - то они и до вызова функции храняться всегда в структуре, а не как отдельные переменные. Компилятору все равно, работать с wrpnt и buf[] или с transmit.wrpnt и transmit.buf[].

 

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

Share this post


Link to post
Share on other sites

Можно пойти ещё дальше, в этой же структуре хранить указатель на функции, которые с ней работают.

Ещё немного, и C++ заново изобретем.

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

Share this post


Link to post
Share on other sites
25 minutes ago, gerber said:

Можно пойти ещё дальше, в этой же структуре хранить указатель на функции, которые с ней работают.

Ещё немного, и C++ заново изобретем.

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

К своему стыду, так и не перешел к использованию С++ как языка с его идеологией. Сначала это были объективные причины, а теперь просто нет желания что-то менять в этой жизни, не вижу профита от таких потрясений. Наверное пенсия скоро- не хотят нейроны на новые орбиты выходить.

Share this post


Link to post
Share on other sites
29.12.2020 в 10:50, ДЕЙЛ сказал:

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);
}

Формально вышеописанный код соответствует коду ниже, если рассматривается только программа целиком, так как есть цепочка вызовов: main() -> func() -> func2 (), где передается  my_array


void func1(void);
void func2(void);

 

#define SIZE_BUF 50

 

uint8_t my_array[SIZE_BUF];

 

void main(void)
{
  func1();
}

 

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

 

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

Edited by uk_denis

Share this post


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

2) При работе с не глобальными объектами вернет размер указателя на элемент массива...

 Серьезно? Код

void func(void)
{
  uint8_t arr[10];
  printf("%u", sizeof(arr));
}

почему-то печатает 10, а не 4:bye:

Share this post


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

 Серьезно? Код


void func(void)
{
  uint8_t arr[10];
  printf("%u", sizeof(arr));
}

почему-то печатает 10, а не 4:bye:

sizeof применен к локальному массиву на стеке. Это не глобальный объект. Локальные объекты функции не являются глобальными объектами.

Share this post


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

Это не глобальный объект.

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

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

sizeof применен к локальному массиву на стеке. Это не глобальный объект.

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

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

При работе с не глобальными объектами вернет размер указателя на элемент массива,

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

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.