Определить размер массива C ++ программно? - PullRequest
60 голосов
/ 13 октября 2008

Этот вопрос был вдохновлен похожим вопросом: Как delete [] «знает» размер массива операндов?

Мой вопрос немного отличается: Можно ли каким-то образом определить размер массива C ++ программным способом? А если нет, то почему? Каждая функция, которую я видел, которая принимает массив, также требует целочисленного параметра, чтобы дать ему размер. Но, как указано в связанном вопросе, delete[] должен знать размер памяти, подлежащей освобождению.

Рассмотрим этот код C ++:

int* arr = new int[256];
printf("Size of arr: %d\n", sizeof(arr));

Это печатает "Size of arr: 4", который является просто размером указателя. Было бы неплохо иметь некоторую функцию, которая печатает 256, но я не думаю, что она существует в C ++. (Опять же, вопрос в том, почему он не существует.)

Уточнение : я знаю, что если бы я объявил массив в стеке вместо кучи (то есть "int arr[256];"), то оператор sizeof вернул бы 1024 (длина массива * sizeof (int) )).

Ответы [ 20 ]

1 голос
/ 13 октября 2008

В общем, нет. Массивы в C и C ++ - это просто блоки памяти без учета информации. Без сохранения длины массива в памяти и добавления дополнительных ресурсов это невозможно в общем случае.

Исключение составляют статические массивы. Например, если вы объявите: int a[50], тогда sizeof(a) будет работать. Это возможно, потому что [50] является частью статического типа массива: он известен компилятору. sizeof интерпретируется во время компиляции.

Однако, если вы создадите указатель: int *p = a, sizeof(p) вернет размер указателя, как вы упомянули, а не размер массива, потому что компилятор не знает, на что указывает p

1 голос
/ 13 октября 2008

К сожалению, это невозможно. В C и C ++ программист обязан помнить о длине массива, поскольку длина массива нигде не сохраняется. Delete [] и free () запоминают размер выделенного блока, но они могут выделить больше памяти, чем запрошено, поэтому их внутренние структуры данных, хранящие размеры выделенных блоков памяти, могут не дать вам точный размер вашего массива.

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

1 голос
/ 13 октября 2008

Вы не можете, по сути:

void foo(int* arr);

int arr[100] = {0};

foo(arr+1); // Calls foo with a pointer to 100-1 elements.

Массив C ++ - это не что иное, как набор объектов, которые хранятся в непрерывной области памяти. Поскольку между ними нет дыр (отступы внутри объектов), вы можете найти следующий элемент массива, просто увеличив указатель. На уровне процессора это простая настройка. C ++ вставляет только множитель sizeof (элемента).

Обратите внимание, что реализации могут выбрать реализацию "жирных указателей", которые содержат границы массивов. Они должны быть в два раза больше, так как вам нужно будет ссылаться на какой-то «дескриптор, связанный с массивом». Как побочный эффект, на таких реализациях вы могли бы вызвать delete [] (1+new int[5]);

1 голос
/ 13 октября 2008

Нет, нет никакого способа сделать это, вы должны следить за тем, насколько он велик внешне. Классы типа std::vector делают это для вас.

0 голосов
/ 12 января 2015

Я делаю это путем деления размера массива на размер первого элемента

int intarray[100];
printf ("Size of the array %d\n", (sizeof(intarray) / sizeof(intarray[0]));

печатает 100

0 голосов
/ 26 октября 2012

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

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

0 голосов
/ 20 сентября 2012

Когда вы создаете указатели на массивы (Создайте оболочку с шаблоном для указателей), вы не можете, но когда вы создаете массив объектов, Вы можете получить размер массива следующим образом:

char* chars=new char[100];
printf("%d",*((int*)chars-1));

Функция delete[] должна деконструировать все объекты в ней. для этого ключевое слово new[] устанавливает количество элементов за всем массивом.

Тело массива выглядит так:

int count;
ObjectType* data; //This value is returned when using new[]
0 голосов
/ 07 января 2009

Компилятор не может знать, что

char *ar = new char[100] 

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

Если вы хотите узнать размер данного массива, просто используйте std :: vector. std :: vector - лучший массив просто.

0 голосов
/ 16 октября 2008

@ Дима,

Как компилятор узнает, каков размер p?

Компилятор должен знать размер p; в противном случае он не может реализовать delete[]. Компилятору не нужно никому говорить, как он это вычисляет.

Для забавного способа убедиться в этом, сравните указатель, возвращаемый operator new[], с указателем, возвращенным new[].

0 голосов
/ 16 октября 2008

Есть ли способ определить размер массива C ++ программным способом? А если нет, то почему?

  1. Нет, если вы сами не отслеживаете это.
  2. Потому что, если компилятору не нужно никому рассказывать об этой информации, кроме себя, он меньше ограничивает компилятор. Желательно это или нет, остается предметом споров.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...