Во-первых, вот код:
int main()
{
int days[] = {1,2,3,4,5};
int *ptr = days;
printf("%u\n", sizeof(days));
printf("%u\n", sizeof(ptr));
return 0;
}
Есть ли способ узнать размер массива, на который ptr
указывает (вместо того, чтобы просто указать его размер, который составляет четыре байта в 32-битной системе)?
Ответы:
Нет, ты не можешь. Компилятор не знает, на что указывает указатель. Существуют хитрости, такие как завершение массива с известным значением вне диапазона, а затем подсчет размера до этого значения, но он не используется
sizeof()
.Другой трюк, упомянутый Заном , это где-то спрятать размер. Например, если вы динамически распределяете массив, выделите блок на одно целое больше, чем тот, который вам нужен, сохраните размер в первом целом и верните
ptr+1
как указатель на массив. Когда вам нужен размер, уменьшите указатель и посмотрите на спрятанное значение. Просто не забудьте освободить весь блок, начиная с самого начала, а не только массив.источник
Ответ - нет."
Программисты на C хранят где-то размер массива. Это может быть частью структуры, или программист может использовать немного
malloc()
больше памяти, чем запрошено, чтобы сохранить значение длины до начала массива.источник
Для динамических массивов ( malloc или C ++ new ) вам необходимо сохранить размер массива, как было упомянуто другими, или, возможно, создать структуру менеджера массива, которая обрабатывает операции добавления, удаления, подсчета и т. Д. К сожалению, C не делает это так же хорошо, как C ++, поскольку вам, в основном, приходится создавать его для каждого сохраняемого вами типа массива, что обременительно, если у вас есть несколько типов массивов, которыми нужно управлять.
Для статических массивов, таких как в вашем примере, есть общий макрос, используемый для получения размера, но он не рекомендуется, поскольку он не проверяет, является ли параметр действительно статическим массивом. Макрос используется в реальном коде, например, в заголовках ядра Linux, хотя он может немного отличаться от приведенного ниже:
Вы можете гуглить по причинам, опасающимся подобных макросов. Быть осторожен.
Если возможно, C ++ stdlib, такой как vector, намного безопаснее и проще в использовании.
источник
ARRAY_SIZE
макрос всегда работает, если его аргумент является массивом (то есть выражением типа массива). Для вашего так называемого «динамического массива» вы никогда не получите фактический «массив» (выражение типа массива). (Конечно, вы не можете, так как типы массивов включают их размер во время компиляции.) Вы просто получаете указатель на первый элемент. Ваше возражение «не проверяет, является ли параметр действительно статическим массивом», на самом деле недопустимо, так как они отличаются, поскольку один является массивом, а другой - нет.Существует чистое решение с шаблонами C ++, без использования sizeof () . Следующая функция getSize () возвращает размер любого статического массива:
Вот пример со структурой foo_t :
Вывод:
источник
T (&)[SIZE]
. Можете ли вы объяснить, что это значит? Также вы можете упомянуть constexpr в этом контексте.SIZE
как аргумент, это параметр шаблона, который имеет быть уже известным по определению функции.)Для этого конкретного примера, да, есть, ЕСЛИ вы используете typedefs (см. Ниже). Конечно, если вы сделаете это таким образом, вы также можете использовать SIZEOF_DAYS, поскольку вы знаете, на что указывает указатель.
Если у вас есть указатель (void *), который возвращается функцией malloc () или тому подобным, то нет, нет способа определить, на какую структуру данных указывает указатель, и, следовательно, нет способа определить его размер.
Вывод:
источник
Поскольку все правильные ответы заявили, вы не можете получить эту информацию только из значения затухшего указателя массива. Если потерянный указатель является аргументом, полученным функцией, тогда размер исходного массива должен быть предоставлен другим способом, чтобы функция узнала этот размер.
Вот предложение, отличное от того, что было предоставлено до сих пор, которое будет работать: вместо этого передайте указатель на массив. Это предложение похоже на предложения стиля C ++, за исключением того, что C не поддерживает шаблоны или ссылки:
Но это предположение несколько глупо для вашей проблемы, поскольку функция определена, чтобы точно знать размер передаваемого массива (следовательно, совсем не нужно использовать sizeof в массиве). Что он делает, тем не менее, предлагает некоторый тип безопасности. Это запретит вам передавать массив нежелательных размеров.
Если предполагается, что функция может работать с массивом любого размера, вам нужно будет указать ее размер в качестве дополнительной информации.
источник
Там нет волшебного решения. С не является рефлексивным языком. Объекты не знают автоматически, что они есть.
Но у вас есть много вариантов:
источник
Мое решение этой проблемы состоит в том, чтобы сохранить длину массива в struct Array в качестве мета-информации о массиве.
Но вам нужно позаботиться о том, чтобы установить правильную длину массива, который вы хотите сохранить, потому что нет способа проверить эту длину, как объяснили наши друзья.
источник
Вы можете сделать что-то вроде этого:
источник
Нет, вы не можете использовать,
sizeof(ptr)
чтобы найти размер массива, наptr
который указывает.Хотя выделение дополнительной памяти (больше, чем размер массива) будет полезно, если вы хотите сохранить длину в дополнительном пространстве.
источник
Размер дня [] равен 20, что не относится к элементам * размер его типа данных. Хотя размер указателя равен 4 независимо от того, на что он указывает. Потому что указатель указывает на другой элемент, сохраняя его адрес.
источник
array_size передает переменную размера :
Использование это:
источник
В строках есть
'\0'
символ в конце, поэтому длину строки можно получить с помощью таких функций, какstrlen
. Например, проблема с целочисленным массивом состоит в том, что вы не можете использовать любое значение в качестве конечного значения, поэтому одним из возможных решений является обращение к массиву и использование в качестве конечного значенияNULL
указателя.источник
NULL
является, вероятно, наименее эффективной альтернативой, которую можно только представить для хранения отдельного элементаsize
. Особенно, если вы действительно используете этот дополнительный слой косвенности все время.