реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Вопрос по размеру массива
Vladimir_T
сообщение Mar 17 2009, 16:53
Сообщение #1


Знающий
****

Группа: Свой
Сообщений: 517
Регистрация: 7-02-06
Пользователь №: 14 073



Здравствуйте, уважаемые коллеги, помогите пожалуйста. В функции мне нужно знать количество элементов массива, делаю это с помощью макроса 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)
Go to the top of the page
 
+Quote Post
sergeeff
сообщение Mar 17 2009, 17:18
Сообщение #2


Профессионал
*****

Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007



При передаче указателя на массив в функцию информация о размере массива становится недоступной. Один из вариантов решения - использовать класс, эмулирующий массив и содержащий функцию .size().
Go to the top of the page
 
+Quote Post
Qwertty
сообщение Mar 17 2009, 17:34
Сообщение #3


Местный
***

Группа: Свой
Сообщений: 408
Регистрация: 21-10-06
Из: Санкт-Петербург
Пользователь №: 21 527



Передавайте размер. sizeof не функция, а скорее макрос. Результат рассчитывается на этапе компиляции.
Go to the top of the page
 
+Quote Post
meister
сообщение Mar 17 2009, 18:44
Сообщение #4


Местный
***

Группа: Участник
Сообщений: 219
Регистрация: 20-11-07
Пользователь №: 32 484



Цитата(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;
}
Go to the top of the page
 
+Quote Post
sergeeff
сообщение Mar 17 2009, 19:50
Сообщение #5


Профессионал
*****

Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007



Результат компиляции в 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]'
Go to the top of the page
 
+Quote Post
meister
сообщение Mar 17 2009, 19:54
Сообщение #6


Местный
***

Группа: Участник
Сообщений: 219
Регистрация: 20-11-07
Пользователь №: 32 484



Цитата(sergeeff @ Mar 17 2009, 23:50) *
Результат компиляции в Visual Studio 6.0


Нашли чем компилировать.
Go to the top of the page
 
+Quote Post
sergeeff
сообщение Mar 17 2009, 20:38
Сообщение #7


Профессионал
*****

Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007



Да, действительно, в VS2008 - без проблем. Изящно!
Go to the top of the page
 
+Quote Post
ar__systems
сообщение Mar 18 2009, 02:07
Сообщение #8


self made
****

Группа: Свой
Сообщений: 855
Регистрация: 7-03-09
Из: Toronto, Canada
Пользователь №: 45 795



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


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

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

Сообщение отредактировал ar__systems - Mar 18 2009, 02:12
Go to the top of the page
 
+Quote Post
VAI
сообщение Mar 18 2009, 04:50
Сообщение #9


Профессионал
*****

Группа: Модераторы
Сообщений: 1 120
Регистрация: 17-06-04
Пользователь №: 37



Добавьте в "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'?


--------------------
Если зайца бить, его можно и спички научить зажигать
Сколько дурака не бей - умнее не будет. Зато опытнее
Go to the top of the page
 
+Quote Post
zhevak
сообщение Mar 18 2009, 05:14
Сообщение #10


Знающий
****

Группа: Свой
Сообщений: 723
Регистрация: 29-08-05
Из: Березовский
Пользователь №: 8 065



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

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

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

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

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

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

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

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

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

Мы все когда были на Вашем месте, и тоже не знали как правилно делать. Почитайте K&R, почитайте Страуструпа. И удачи Вам в освоении языка!


--------------------
Хочешь рассмешить Бога -- расскажи ему о своих планах!
Go to the top of the page
 
+Quote Post
richie
сообщение Mar 18 2009, 08:34
Сообщение #11


Частый гость
**

Группа: Свой
Сообщений: 147
Регистрация: 5-07-04
Из: Обнинск
Пользователь №: 261



+1, zhevak.
Сказал, то что я не мог сказать с утра, т.к. форум был недоступен.
Поэтому, просто присоединюсь!
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Mar 18 2009, 08:49
Сообщение #12


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



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


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Mar 18 2009, 08:50
Сообщение #13


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(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]))


Теперь результат выпендрежа детерминирован, т.к. работает только с объектами статической компиляции. Для кучи уже надо не лениться и указывать тип объекта. Тут не лаконично
Go to the top of the page
 
+Quote Post
zhevak
сообщение Mar 18 2009, 09:40
Сообщение #14


Знающий
****

Группа: Свой
Сообщений: 723
Регистрация: 29-08-05
Из: Березовский
Пользователь №: 8 065



Цитата(richie @ Mar 18 2009, 13:34) *
Поэтому, просто присоединюсь!

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

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

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

А, вообще, где сам топикстартер?
А то мы как всегда между собой бурно обсуждаем тему "от кого там Клавка родила" (С),
а реальное-то состояние дел совсем другое.


--------------------
Хочешь рассмешить Бога -- расскажи ему о своих планах!
Go to the top of the page
 
+Quote Post
ar__systems
сообщение Mar 18 2009, 11:39
Сообщение #15


self made
****

Группа: Свой
Сообщений: 855
Регистрация: 7-03-09
Из: Toronto, Canada
Пользователь №: 45 795



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

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

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

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

Сообщение отредактировал ar__systems - Mar 18 2009, 11:42
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th July 2025 - 14:16
Рейтинг@Mail.ru


Страница сгенерированна за 0.01546 секунд с 7
ELECTRONIX ©2004-2016