Подтвердить что ты не робот

Размер массива в 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. Любые идеи почему? Спасибо заранее!

4b9b3361

Ответ 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.