Размер массива в c
простой вопрос, который меня устраивает.
Скажем, у меня есть массив, определенный в основном так: int arr[5]
. Теперь, если я все еще внутри main, и я установил int i = sizeof(arr)/sizeof(arr[0])
, тогда мне будет 5, но если я передам массив как параметр функции и сделаю то же вычисление в этой функции, я получаю другое число. Почему это? Сначала я думал, что это потому, что в функции arr
есть указатель, но насколько я знаю, arr
является указателем внутри main!
Кроме того, если я делаю что-то очень похожее, только я инициализирую массив динамически, я получаю странные результаты:
int *arr = (int*) malloc(sizeof(int) * 5);
int length = sizeof(*arr) / sizeof(arr[0]);
printf("%d\n",length);
Здесь вывод 1
. Любые идеи почему?
Спасибо заранее!
Ответы
Ответ 1
C массивы не хранят свои собственные размеры нигде, поэтому sizeof
работает только так, как вы ожидаете, если размер известен во время компиляции. malloc()
обрабатывается компилятором как любая другая функция, поэтому sizeof
не может сказать, что arr
указывает на первый элемент массива, не говоря уже о том, насколько он большой. Если вам нужно знать размер массива, вам нужно явно передать его в свою функцию либо в виде отдельного аргумента, либо с помощью структуры, содержащей указатель на ваш массив и его размер.
Ответ 2
Это потому, что arr теперь является указателем, и он может указывать на один int или массив из 1000 ints, который функция просто не знает. Вам нужно будет передать размер массива в функцию.
В основном arr объявляется как int [5], и поэтому размер может быть вычислен компилятором.
Ответ 3
Я не понял первый вопрос (напишите какой-нибудь код, пожалуйста), но для второго:
sizeof(*arr) ; // is sizeof(int) as arr is of type "int *"
sizeof(arr[0]) ; // is sizeof(int), as arr[0] is the first
// item of an array of int
Факт: *arr
и arr[0]
означают то же самое, но говорят по-другому. Действительно, пусть n - индекс: *(arr + n)
совпадает с arr[n]
.
Ответ 4
насколько я знаю, arr также является указателем внутри main!
Это ошибка. В main
, где вы определили int arr[5]
, arr
- это массив, а не указатель. Его размер равен размеру массива, поэтому 5*sizeof(int)
. Когда вы передавали его как параметр функции, этот параметр имел тип int*
, поэтому внутри функции вы делали размер int*
, а не int[5]
.
Здесь вывод 1. Любые идеи, почему?
На этот раз arr
действительно является указателем, так как вы объявили его int *arr
. Но в любом случае, будь то int *arr
или int a[5]
, *arr
и arr[0]
означают то же самое: первый элемент. Поэтому, конечно, они имеют одинаковый размер, а sizeof(*arr) / sizeof(arr[0])
равен 1.
Ответ 5
Это из-за разницы между массивом известного размера и указателем на массив неизвестного размера. sizeof
выполняется во время компиляции, и компилятор не может заранее сообщить размер динамически созданной области памяти.
Ответ 6
Вы должны понимать разницу между статическими и динамическими массивами. Статические массивы - это такие типы, как int
, float
, double
и т.д. Они разные. Даже
int a[10];
имеет другой тип от
int b[11];
Во время компиляции количество элементов в статических массивах известно, а оператор sizeof
возвращает число байтов, которые они занимают.
С указателями, которые были инициализированы, либо указывать на какую-либо переменную, либо на выделенную память, во время выполнения было бы очевидно, где они указывают, и компилятор не может определить, каков будет размер этого массив в будущем. Поэтому указатель sizeof
дает вам 4 (или 8 в 64 битах), например.
Обратите внимание, что оператор sizeof
работает во время компиляции, а не во время выполнения.
Если вам нужно знать размер выделенной памяти (через malloc
), у вас нет выбора, кроме как сохранить размер массива в другой переменной, например, сразу после того, как вы сделали malloc
.