Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Для новичков > Узнать размер динамического массива


Автор: TheDestroyer 2.4.2009, 13:04
Возможно ли узнать размер динамического массива?
Код

int *ar;    // указатель на элемент массива
int size=100;

ar=new int[size];        //Выделение памяти
memset(ar,0,size);    //Инициализация
size = sizeof(ar); // выдает 4

delete[] ar;            //Удаление


Похоже, что размер динамического массива узнать в C++, (у меня Borland C++) невозможно, и надо каждый раз передавать его размер как параметр. Это так?
Спасибо

Автор: Alca 2.4.2009, 13:07
Цитата

невозможно

Возможно если массив это сишная строка
Код

strlen(size);


Добавлено через 34 секунды
В других случаях надо передавать размер массива.

Добавлено через 1 минуту и 5 секунд
Цитата

Код

size = sizeof(ar); // выдает 4


Это размер указателя

Автор: zim22 2.4.2009, 13:14
Цитата(TheDestroyer @  2.4.2009,  13:04 Найти цитируемый пост)
 и надо каждый раз передавать его размер как параметр

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

Автор: Dmi3ev 2.4.2009, 13:14
Цитата

size = sizeof(ar);

когда ты так пишешь ты должен понимать, что ar - это не массив, это всего лишь указатель... и размер массива массива ( 1 или 1000 элементов) никак не касается указателя...
а если ты хочешь узнать объем в байтах, то можно просто после выделения памяти посчитать
Код

int *ar;    // указатель на элемент массива
int size=100;
ar=new int[size];        //Выделение памяти
memset(ar,0,size);    //Инициализация
int size1=sizeof(int)*size;
delete[] ar;  

Автор: Alca 2.4.2009, 13:22
заверни свои данные в структуру и передавай ее в функцию

Автор: zim22 2.4.2009, 13:22
Цитата(Dmi3ev @  2.4.2009,  13:14 Найти цитируемый пост)
int size1=sizeof(int)*size;

Гугл рекомендует не использовать sizeof от типа.
лучше написать 
Код

int size1=sizeof(size)*size;

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

Автор: mes 2.4.2009, 13:37
Цитата(zim22 @  2.4.2009,  12:14 Найти цитируемый пост)
один из способов избежать передачи размера в качестве отдельного параметра заключается в передачи пары итераторов на начало массива и на элемент после его конца.
ещё один способ: последний элемент массива инициализировать значением-флагом, при достижении которого вы завершите итерировать его элементы. 

еще один : использовать std::vector и отградить себя от рутинной работы по контролю за динамическим массивом. smile

Автор: azesmcar 2.4.2009, 13:39
Цитата

ещё один способ: последний элемент массива инициализировать значением-флагом, при достижении которого вы завершите итерировать его элементы. 

а может лучше в первом байте хранить размер и не считать в таком случае smile
Код

template <class T>
T* newArray(size_t count) {
    T* r = new T[count + 1];
    r[0] = count;
    return ++r;
}

template <class T>
void deleteArray(T* p) {
    delete [] --p;
}

template <class T>
int sizeofArray(T* p) {
    return *(p - 1);
}

что-то вроде этого

Автор: mrbrooks 2.4.2009, 13:39
TheDestroyer, используй std::vector и не ломай мозг.

Автор: mrbrooks 2.4.2009, 13:40
mes, припозднился  smile 

Автор: azesmcar 2.4.2009, 13:40
по любому у этих методов полно недостатков, лучше передавать..либо в структуре, либо просто так..без разницы

Добавлено через 2 минуты и 3 секунды
а еще лучше - как сказали 
mrbrooks, 
mes используй вектор

Автор: Anikmar 2.4.2009, 13:47
Цитата(mes @  2.4.2009,  13:37 Найти цитируемый пост)
еще один : использовать std::vector и отградить себя от рутинной работы по контролю за динамическим массивом.

Если это массив собственных классов - попутно наградить себя определением соответствующих конструкторов и операторов smile 

Автор: zim22 2.4.2009, 13:47
Цитата(TheDestroyer @  2.4.2009,  13:04 Найти цитируемый пост)
Возможно ли узнать размер динамического массива?

размер статических массивов неявно передаётся в функцию в качестве параметра
Код
template <typename T, size_t size>
size_t get_size(const T (&arr)[size]) {
  return size;
}
int _tmain(int argc, _TCHAR* argv[])
{
  int arr[25];
  size_t size = get_size(arr);
    return 0;
}





Автор: ISergeyN 2.4.2009, 14:03
А если так 
Код

#include <iostream>
using namespace std;

template<typename T> 
inline int arrlen(T *arr)
{
    return static_cast<int>(_msize(arr)/sizeof(T));
}

int main()
{
    int *arr = new int[100];

    cout<<arrlen(arr)<<endl;

    delete[] arr;

    return 0;
}

Автор: Dmi3ev 2.4.2009, 14:15
Цитата

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

а зачем size другого типа, если я пишу:
Код

ar=new int[size]; 
 
хотя согласен, он может быть и беззнаковый и тд...
но size в данном случае не влияет на размер одного элемента, влияние оказывает new int, соответственно как раз так писать
Цитата

int size1=sizeof(size)*size;

ненадежно!
потому как, size - это количество элементов, и эта переменная будет неизменна, независимо от того какого типа будет массив и тд...

zim22, ты в этот раз не прав...

Автор: mrbrooks 2.4.2009, 14:20
 smile 
хм. ребзя предлагаю объявить конкурс на самые лучшие костыли.

Автор: Soah 2.4.2009, 14:20
Dmi3ev, думаю zim22 хотел написать
Код

int size1=sizeof(ar[0])*size;

Автор: zim22 2.4.2009, 14:25
Цитата(Dmi3ev @  2.4.2009,  14:15 Найти цитируемый пост)
zim22, ты в этот раз не прав...

для этого случая непринципиально было, передавать в sizeof тип или название элементов.
но есть большое НО. во всех остальный случаях это принципиально. smile т.к. нет ничего проще забыть изменить тип в sizeof, после того, как тип переменной изменили. Я думаю вы со мной согласитесь.

Добавлено через 1 минуту и 30 секунд
Цитата(Soah @  2.4.2009,  14:20 Найти цитируемый пост)
думаю zim22 хотел написать

телепатией владеете? научите!

Автор: Soah 2.4.2009, 14:51
Цитата(zim22 @  2.4.2009,  14:25 Найти цитируемый пост)
телепатией владеете? научите!

я что-то неправильно написал?

Цитата(zim22 @  2.4.2009,  13:22 Найти цитируемый пост)

Код

int size1=sizeof(size)*size;

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

Код

int *ar;    
long size=100;
ar=new int[size];       
memset(ar,0,size);    
int size1=sizeof(size)*size;
delete[] ar; 

думаешь так правильно smile 

Автор: zim22 2.4.2009, 15:05
Цитата(Soah @  2.4.2009,  14:20 Найти цитируемый пост)
Dmi3ev, думаю zim22 хотел написать код C++1:int size1=sizeof(ar[0])*size;

думаешь так правильно  smile 

Автор: Dmi3ev 2.4.2009, 15:08
zim22, правильнее, чем
Код

int size1=sizeof(size)*size;

это абсолютно то же самое, что взять переменную постороннюю совсем и написать вот так
Код

int a;
int size1=sizeof(a)*size;

те ни в склад, ни в лад, поцелуй дрова в живот получается...

Автор: zim22 2.4.2009, 15:14
Dmi3ev, http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#sizeof
только открывайте любым браузером, кроме Оперы. иначе половину текста не увидите smile

Автор: Soah 2.4.2009, 15:15
zim22, а сколько будет в size1, в твоём варианте, и сколько в варианте Dmi3ev`a
sizeof(int)*size != sizeof(long)*size
Цитата(zim22 @  2.4.2009,  15:05 Найти цитируемый пост)
думаешь так правильно

а что не правильно?

Автор: zim22 2.4.2009, 15:18
Цитата(Soah @  2.4.2009,  15:15 Найти цитируемый пост)
а что не правильно?

акцент необходимо было делать не на конкретном значении, это не принципиально важно,  а на приёме, который используется для минимизации возможных будущих потенциальных ошибок, связанных с передачей в sizeof не переменной, а типа. почитайте ссылку, что я выше дал на Гугл.

Автор: Soah 2.4.2009, 15:23
Цитата

Use sizeof(varname) instead of sizeof(type) whenever possible. 

а с чего ты взял что varname в данном случае size?

и что не правильно в моём варианте?

Автор: zim22 2.4.2009, 15:37
Цитата(Soah @  2.4.2009,  15:23 Найти цитируемый пост)
 с чего ты взял что varname в данном случае size?и что не правильно в моём варианте?

точно. в sizeof нужно было заключать не size, а &ar[0].  smile 
так что, да, я был не прав. 

Автор: Dov 2.4.2009, 15:48
Цитата(zim22 @  2.4.2009,  15:37 Найти цитируемый пост)
точно. в sizeof нужно было заключать не size, а &ar[0].


не &ar[0], а ar[0], т. е. не указатель на эл-нт, а его значение

Автор: Dmi3ev 2.4.2009, 16:11
Цитата

не &ar[0], а ar[0], т. е. не указатель на эл-нт, а его значение

 smile 
zim22, я тебе про то же, и Soah...
короче вот так надо:
Код

int size1=sizeof(ar[0])*size;

Автор: zim22 2.4.2009, 17:11
всё-равно не правильно.
лучше тип передать, а не значение переменной.
если у нас будет 
Код

long size=0;

то обращение к элементу по индексу 0, которого не существует считает мусор... 

Автор: Dmi3ev 2.4.2009, 17:19
Цитата

то обращение к элементу по индексу 0, которого не существует считает мусор...  

можно условие написать, что если равно 0, то вернуть 0... короче, хватит... бредовое уже обсуждение пошло...

Автор: zim22 2.4.2009, 17:21
кстати, правильно обнулить элементы так надо:
Код

memset(ar,0,sizeof(int) * size);    

Автор: mes 2.4.2009, 17:21
Цитата(zim22 @  2.4.2009,  16:11 Найти цитируемый пост)
то обращение к элементу по индексу 0, которого не существует считает мусор... 

нельзя ли тут поподробней ? при чем тут мусор ? и вообще речь идет о sizeof(*array) или я чего то упустил ?

Добавлено через 1 минуту и 12 секунд
Цитата(zim22 @  2.4.2009,  16:21 Найти цитируемый пост)
кстати, правильно обнулить элементы так надо:

 а где соблюдение рекомендации от гугля ?

Автор: Soah 2.4.2009, 17:25
zim22, 
Код

long *ar;    
int size=100;
ar=new long[size];       
memset(ar,0,size);    
int size1=sizeof(ar[0])*size;
delete[] ar; 
cout << size1;


Код

long *ar;    
int size=100;
ar=new long[size];       
memset(ar,0,size);    
int size1=sizeof(&ar[0])*size;
delete[] ar; 
cout << size1;

посмотри что будет

Цитата(zim22 @  2.4.2009,  17:11 Найти цитируемый пост)
long size=0;

Цитата(Dmi3ev @  2.4.2009,  17:19 Найти цитируемый пост)
можно условие написать

Автор: zim22 2.4.2009, 17:27
Цитата(mes @  2.4.2009,  17:21 Найти цитируемый пост)
 а где соблюдение рекомендации от гугля ?

гугл меня простит.
Цитата(mes @  2.4.2009,  17:21 Найти цитируемый пост)
? и вообще речь идет о sizeof(*array) или я чего то упустил ?

sizeof(*array) или sizeof(array[0]) - разницы ведь нет? (я уже запутался окончательно %) )
это обращение к первому элементу массива. А если переменная мы пишем в коде int size=0;
то *array будет содержать мусор. smile 

Автор: Soah 2.4.2009, 17:30
Цитата(zim22 @  2.4.2009,  17:27 Найти цитируемый пост)
то *array будет содержать мусор.

нас интересует тип, а не значение

Автор: Anikmar 2.4.2009, 17:30
Цитата(zim22 @  2.4.2009,  17:27 Найти цитируемый пост)
sizeof(*array)

Никакого обращения к элементу здесь нет. Результат выражения считается при компиляции.

Автор: zim22 2.4.2009, 17:34
Цитата(Anikmar @  2.4.2009,  17:30 Найти цитируемый пост)
Никакого обращения к элементу здесь нет. Результат выражения считается при компиляции.

Я этого не знал. Всем спасибо за наставления smile

Автор: mes 2.4.2009, 17:34
Цитата(zim22 @  2.4.2009,  16:27 Найти цитируемый пост)
sizeof(*array) или sizeof(array[0]) - разницы ведь нет? (я уже запутался окончательно %) )

 smile 
Цитата(Anikmar @  2.4.2009,  16:30 Найти цитируемый пост)
Никакого обращения к элементу здесь нет. Результат выражения считается при компиляции. 

 smile 

Автор: Dmi3ev 2.4.2009, 17:58
короче, я так понимаю, мы пришли к такому варианту, учитывая все наши обсуждения)))
Код

//...
long *ar;    
int size=100;
if (size<=0)
{
    cout<<"error: size must be >0";
    return -1;//если функция возвращает целое значение
}
ar=new long[size];           
int size1=sizeof(ar[0])*size;//мне кажется так все лучше...
memset(ar, 0, size1);//сначала посчитали размер, потом обнулили, потому как memset(ar,0,size) не очень правильно...
//...
delete[] ar;
cout << size1;
//...

Автор: Alca 2.4.2009, 18:06
макрос ARRAYSIZE Есть

Добавлено через 14 секунд
 smile

Добавлено через 1 минуту
Код

int iSize = ARRAYSIZE(ArrayName);

Автор: andrew_121 2.4.2009, 18:14
Alca, Простите, Уважаемая, а можно взглянуть на расширенный текст сего макроса?

Автор: mes 2.4.2009, 18:17
Цитата(andrew_121 @  2.4.2009,  17:14 Найти цитируемый пост)
Alca, Простите, Уважаемая, 

Цитата(Profile of Alca)

Пол Мужской

smile

Цитата(Alca @  2.4.2009,  17:06 Найти цитируемый пост)
макрос ARRAYSIZE Есть

насколько я помню он для статических массивов и звучит примерно так  
Код

#define ARRAYSIZE(array) sizeof(array)/sizeof(*array)

Автор: andrew_121 2.4.2009, 18:24
Цитата(mes @  2.4.2009,  18:17 Найти цитируемый пост)
Цитата(Profile of Alca)

Пол Мужской

smile

Глупо получилось smile  За то смешно... smile 

Автор: Dov 2.4.2009, 18:47
Цитата(Dmi3ev @  2.4.2009,  17:58 Найти цитируемый пост)
короче, я так понимаю, мы пришли к такому варианту, учитывая все наши обсуждения)))

Мне кажется, что все здесь запутались и не понимают, что имел ввиду ТС. Я думаю, что он имел ввиду следующее.
Допустим у него есть такой код:
Код

void func(int * mas)
{
    int size;    

    // здесь он хочет узнать размер массива, что бы работать с ним дальше
    size = /* ??? */ ;
    memset(mas, 0, size);    //Инициализация
    // ...
}

int main()
{
    int * ar;                  // указатель на элемент массива
    int   size;                // размер массива

    cout << "Ведите размер массива: ";
    cin  >> size;

    ar = new int[size];        //Выделение памяти

    // ...
    func(ar);
    // ...

    delete[] ar;               //Удаление

    return 0;
}

По-моему, что-то такое и хотел узнать ТС..   smile 



Автор: Soah 2.4.2009, 18:55
Dov, мы конечно немного отошли от темы, но ведь есть и решение
http://forum.vingrad.ru/index.php?showtopic=253934&view=findpost&p=1831345

Автор: Dov 2.4.2009, 19:04
Soah, я не уверен, что это решение подойдёт к 
Цитата(TheDestroyer @  2.4.2009,  13:04 Найти цитируемый пост)
(у меня Borland C++) 


Добавлено через 3 минуты и 18 секунд
к тому же, _msize возвращает размер памяти, выделенной при помощи сишных ф-ций:  malloc и т.д. но не с помощью new. ИМХО.

Автор: Soah 2.4.2009, 19:22
Код

#include <iostream.h>
#include <malloc.h>

int main()
{
        int size = 200;
        long* ar = new long[size];

        cout << (_msize(ar)/sizeof(ar[0]));

        delete [] ar;
        cin.get();
        return 0;
}

Borland C++ 5, всё работает.

Автор: Dov 2.4.2009, 19:26
Цитата(Soah @  2.4.2009,  19:22 Найти цитируемый пост)
Borland C++ 5, всё работает.

Ну, тогда и слава Б-гу.    smile 

Автор: TheDestroyer 3.4.2009, 13:00
Спасибо большое за советы. 
Похоже, наилучший вариант по моему вопросу:

Цитата(Soah @  2.4.2009,  19:22 Найти цитируемый пост)

#include <iostream.h>
#include <malloc.h>
int main()
{
        int size = 200;
        long* ar = new long[size];
        cout << (_msize(ar)/sizeof(ar[0]));
        delete [] ar;
        cin.get();
        return 0;
}

Выдает ошибку
[Linker Error] Unresolved external '__msize' referenced from D:\...\UNIT1.OBJ
Подскажите плз как справиться.

Автор: Soah 3.4.2009, 13:37
http://forum.codenet.ru/showthread.php?t=26390

Автор: SerK 1.12.2016, 17:28
Количество элементов в массие

Код

String smass [] = {".","..","...","!","?","!?","?!"};
    int cou =  sizeof(smass)/sizeof(int);

Автор: Alca 1.12.2016, 17:31
Это динамический массив, бро?

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)