Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Вопрос по размеру массива
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Vladimir_T
Здравствуйте, уважаемые коллеги, помогите пожалуйста. В функции мне нужно знать количество элементов массива, делаю это с помощью макроса SizeObj, а он в данной функции не работает. Компилятор - Кейл. Можно было бы передавать размер массива в саму функцию, но это не то. Вызывается эта функция часто и для массивов разной длины, потому хотелось лаконичнее, да еще бы с передачей в функцию указателя на массив, но по указателю на массив я не могу определить размер. Как бы решить эту задачку.

Код
typedef struct
{
  int X;
  int Y;
  char  dX;
  char  dY;
} TG_Buttons;

TG_Buttons G_But [] = {
                              Bt_Menu_X, Bt_Menu_Y, Bt_Menu_L, Bt_Menu_H,
                              Bt_Prn_X, Bt_Prn_Y, Bt_Prn_L, Bt_Prn_H,
                              Bt_Rec_X, Bt_Rec_Y, Bt_Rec_L, Bt_Rec_H
                          
                       };


#define     SizeObj(a) (sizeof(a) / sizeof(a[0]))

void Set_Arr_But (TG_Buttons G_Bt [])
{ INT16U i;
  TG_Buttons *pG_But = &G_Bt [0];
  float k_Y;
      
   k_Y = (float)Max_TSC_Y / LCD_YSIZE;  

for (i=0; i < SizeObj(G_Bt); i++)
  {
    pG_But->Y = ceil ((pG_But->Y + pG_But->dY/2) * k_Y);             //
    pG_But ++;
  }
} // Set_Arr_Buttons (void)
sergeeff
При передаче указателя на массив в функцию информация о размере массива становится недоступной. Один из вариантов решения - использовать класс, эмулирующий массив и содержащий функцию .size().
Qwertty
Передавайте размер. sizeof не функция, а скорее макрос. Результат рассчитывается на этапе компиляции.
meister
Цитата(Vladimir_T @ Mar 17 2009, 20:53) *
Как бы решить эту задачку.


Код
template <class T, unsigned N> void kisa(T (&a)[N])
{
    printf("%p %u\n", a, N);
}

int main(int argc, char* argv[])
{
    int a[7];
    char q[11];

    kisa(a);
    kisa(q);

    return 0;
}
sergeeff
Результат компиляции в Visual Studio 6.0

Цитата
C:\my_proj\VC++\main.cpp(8) : error C2265: '<Unknown>' : reference to a zero-sized array is illegal
C:\my_proj\VC++\main.cpp(18) : error C2784: 'void __cdecl kisa(T (&)[1])' : could not deduce template argument for ' (&)[1]' from 'int [7]'
C:\my_proj\VC++\main.cpp(19) : error C2784: 'void __cdecl kisa(T (&)[1])' : could not deduce template argument for ' (&)[1]' from 'char [11]'
meister
Цитата(sergeeff @ Mar 17 2009, 23:50) *
Результат компиляции в Visual Studio 6.0


Нашли чем компилировать.
sergeeff
Да, действительно, в VS2008 - без проблем. Изящно!
ar__systems
Цитата(sergeeff @ Mar 17 2009, 15:38) *
Да, действительно, в VS2008 - без проблем. Изящно!


Это не изящно, это уродство. Вы представляете как темплайт реализован в компиляторе?

Для каждой длины массива с которой киса вызывается, будет сгенерирована *отдельная* функция. Если киса большая, как-то неразумно.
VAI
Добавьте в "TG_Buttons G_But []" признак конца - ещё 1 элемент со значением Х = -1 (ну или Y).
тогда цикл у Вас будет выглядеть так:
Код
  for (i=0; pG_But->X >= 0; i++)
  {
    pG_But->Y = ceil ((pG_But->Y + pG_But->dY/2) * k_Y);             //
    pG_But ++;
  }

Ведь Вас не смущает, что строка заканчивается символом '\0'?
zhevak
Цитата(Vladimir_T @ Mar 17 2009, 21:53) *
Можно было бы передавать размер массива в саму функцию, но это не то.

Да кто Вам такое сказал? Как раз то самое. Самое простое и самое широкоиспользуемое явление -- передавать в функцию указатель вместе с размерностью массива. Посмотрите на библтотечные функции и убедитесь, что это так и делается.

Цитата
Вызывается эта функция часто и для массивов разной длины, потому хотелось лаконичнее, да еще бы с передачей в функцию указателя на массив

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

Вы видели как дети рисуют картины? Чем детские картины отличаются от картин взрослых? -- Дети стремятся выразить себя не в точности отображения, а в насыщеености и яркости красок. Ни один художник не станет писать свою картину флуоресцентными маркерам. Хотя, в жизни иногда встречваются типа Малевичей... Не важно. Вы понимаете о чем я толкую? Выпендрежный стиль программирования говорит не крутости программиста, а скорее о его кудрявости. Чем больше всяких трюков, тем сложнее (== дольше) отлаживать прогу и сопровождать ее после выхода в свет. Если Вы "играетесь", и результат Вашей работы не имеет никакого значени, то можете делать все что Вам заблагорассудится. Если же Вы намерены делать "по-взрослому", забудьте про витееватость. Делайте как можно проще и понятнее. А свои секреты ппрограммирования защищайте другими способами.

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

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

Замечу, что эти два способа работать будут. Но это не есть "кошерно", хотя смотртся круто.

Делайте как можно проще и понятнее. Такой подход выгоднее со всех точек зрения. И это подтверждается практикой.

Мы все когда были на Вашем месте, и тоже не знали как правилно делать. Почитайте K&R, почитайте Страуструпа. И удачи Вам в освоении языка!
richie
+1, zhevak.
Сказал, то что я не мог сказать с утра, т.к. форум был недоступен.
Поэтому, просто присоединюсь!
Сергей Борщ
Цитата(zhevak @ Mar 18 2009, 07:14) *
Если же размеры массивов разные, то вычисление размера следует производит пере вызовом функции и передвать его как еще один параметр.
А еще можно объединить этот способ с вариантом имени meistera: сделать шаблон "киса" встраиваемой функцией-оберткой, задача которой - подставить количество элементов вторым параметром при вызове реальной функции:
Код
template <class T, unsigned N> inline void kisa(T (&a)[N])
{
  Set_Arr_But (a, N);
}
В этом случае накладных расходов не будет - уникальное тело kisa для каждого набора параметров будет идентично ручному указанию двух параметров.
_Pasha
Цитата(zhevak @ Mar 18 2009, 08:14) *
Самое простое и самое широкоиспользуемое явление -- передавать в функцию указатель вместе с размерностью массива.


+10^10 Он не там макрос организовал:


Код
void somefunc_code( sometype *ptr, size_t obj_size, size_t elem_size);

#define somefunc (obj) somefunc_code(&obj,sizeof(obj),sizeof(obj[0]))


Теперь результат выпендрежа детерминирован, т.к. работает только с объектами статической компиляции. Для кучи уже надо не лениться и указывать тип объекта. Тут не лаконично
zhevak
Цитата(richie @ Mar 18 2009, 13:34) *
Поэтому, просто присоединюсь!

Не возражаю. Welcome!

Цитата(Сергей Борщ)
А еще можно объединить этот способ с вариантом имени meistera: сделать шаблон ...

Да, но...
У Vladimir_T ничего не сказано про язык программирования. Судя по исходнику,
он пишет под счистым С, а не в С++. Поэтому решение с использованием шаблонов тут
как-то не совсем верное получается.

А, вообще, где сам топикстартер?
А то мы как всегда между собой бурно обсуждаем тему "от кого там Клавка родила" (С),
а реальное-то состояние дел совсем другое.
ar__systems
Цитата(zhevak @ Mar 18 2009, 00:14) *
Делайте как можно проще и понятнее. Такой подход выгоднее со всех точек зрения. И это подтверждается практикой.

Yep, это называлось KISS-принцип в одной книжке --- Keep It Simple, Silly smile.gif

Еще один + к вашему посту.

ps/ Я вообще в шоке от того, что начинающего программера пустили программировать на ембеддед девайс....
Vladimir_T
Спасибо всем за дельные советы. Понял, что в простоте залог успеха.
zhevak
Цитата(ar__systems @ Mar 18 2009, 16:39) *
Yep, это называлось KISS-принцип в одной книжке --- Keep It Simple, Silly smile.gif

ага. Я это тоже недавно видел в книжке Эрика Реймонда "Искусство программирования для UNIX".
Только там было Keep it simple, stupid!. (Тяжелая, надо сказать, для чтения книжка, но
"пользительная".)

Цитата
ps/ Я вообще в шоке от того, что начинающего программера пустили программировать на ембеддед девайс....

да всякое бывает. Приятно то, что парень не бегает от проблем, а пытается разобраться. Уважаю таких людей.
Поэтому и помощь оказать не зазорно.
_Pasha
Цитата(ar__systems @ Mar 18 2009, 15:39) *
ps/ Я вообще в шоке от того, что начинающего программера пустили программировать на ембеддед девайс....

Зато не будет потом malloc() или printf() вальяжно использовать. Всегда с оглядкой на ресурсы smile.gif
Vladimir_T
Цитата(ar__systems @ Mar 18 2009, 14:39) *
ps/ Я вообще в шоке от того, что начинающего программера пустили программировать на ембеддед девайс....


Скажите, как мне это удалось? Шокировать ?
ar__systems
Цитата(_Pasha @ Mar 18 2009, 10:48) *
Зато не будет потом malloc() или printf() вальяжно использовать. Всегда с оглядкой на ресурсы smile.gif


Будет smile.gif Переделывал я один проект, так там товарищ использовал 32бит floating point -- это на 8бит контроллере. (а можно было спокойно целыми числами обойтись) Ну просто потому что он на С программировал. И конвертировал он эти float в строку с помощью как раз printf. Ну потом конечно у него даже тривиальные изменения в программе не помещались в память, которой было всего несколько Кб.
_Pasha
Цитата(ar__systems @ Mar 18 2009, 21:11) *
Будет smile.gif

А есть еще менее очевидные штучки, которые  тоже поднадоели - обращаться с дефицитным RAM как с единственным местом обитания строк smile.gif Вместо того, чтобы встраивать уже в выходной поток данных доступ по указателям, пишется все как для компа. Оно и понятно - гемор это не только ценный опыт, но и собсно геморрой. Кому надо усложнять? smile.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.