Почему C-Array имеет неправильное значение sizeof() при передаче функции?
Полный пример:
#include <stdio.h>
void test(int arr[]) {
int arrSize = (int)(sizeof(arr) / sizeof(arr[0]));
printf("%d\n", arrSize); // 2 (wrong?!)
}
int main (int argc, const char * argv[]) {
int point[3] = {50, 30, 12};
int arrSize = (int)(sizeof(point) / sizeof(point[0]));
printf("%d\n", arrSize); // 3 (correct :-) )
test(point);
return 0;
}
Прежде чем передать его функции, sizeof дает мне правильное значение. Выполнение точно такой же вещи в одном и том же массиве в функции дает странные результаты. Там один элемент отсутствует. Почему?
Ответы
Ответ 1
Когда вы передаете массив в функцию в C, массив распадается на указатель на свой первый элемент. Когда вы используете sizeof
для параметра, вы берете размер указателя, а не самого массива.
Если вам нужна функция, чтобы знать размер массива, вы должны передать ее как отдельный параметр:
void test(int arr[], size_t elems) {
/* ... */
}
int main(int argc, const char * argv[]) {
int point[3] = {50, 30, 12};
/* ... */
test(point, sizeof(point)/sizeof(point[0]));
/* ... */
}
Также обратите внимание, что по той же причине (с помощью sizeof
указателя) трюк sizeof(point)/sizeof(point[0])
не работает для динамически распределенного массива, а только массив, выделенный в стеке.
Ответ 2
Поскольку массив разложил на указатель, переданный как аргумент функции, поэтому sizeof
дает вам 4 и 8 для 32- и 64-разрядных платформ соответственно.
Ответ 3
Также важно понять, что sizeof
оценивается в время компиляции. Поскольку в этом случае нет смысла ожидать различного вывода в test()
в зависимости от того, что было передано. Расчет sizeof
выполнялся при компиляции функции.
Ответ 4
Потому что, когда он прошел, фактически передается только указатель на массив.
На ваш вопрос также отвечает Часто задаваемые вопросы по программированию на C > . Вопрос 6.21.
Ответ 5
В C, С++ и Objective-C функции не могут иметь параметры массива. Они могут иметь параметры, которые выглядят как параметры массива, но они не. В вашем примере
void test(int arr[])
компилятор видит "есть параметр, который выглядит как массив int", и он заменяет этот параметр "указателем на int". Таким образом, функция, которую вы написали, абсолютно, на сто процентов, идентична
void test (int* arr)
Следовательно, внутри функции sizeof (arr) вы получите размер "указателя на int".
Ответ 6
Поскольку sizeof() НЕ говорит вам размер массива в C. Он делает что-то совершенно другое.
sizeof Ссылка на С++