Почему размер массива вычисляется неправильно, когда выполняется изнутри функции?

#arrays #c #function #pointers #sizeof

#массивы #c #функция #указатели #sizeof

Вопрос:

Когда я использую этот код в main() функции, размер (или длина) массива вычисляется правильно:

 #include <stdio.h>

int main(void)
{
    int arr[] = {2, 5, 9, 8, 4, 5, 1, 2, 8, 5};
    int length = sizeof(arr) / sizeof(arr[0]);
    printf("The number of elements in the array is %dn", length);
    return 0;
}
 

Выходной сигнал:

 The number of elements in the array is 10
 

Но когда я делаю то же самое с помощью функции, то результат получается неправильным:

 #include <stdio.h>

int sizeTeller(int array[]);

int main(void)
{
    int arr[] = {2, 5, 9, 8, 4, 5, 1, 2, 8, 5};
    printf("The number of elements in the array is %dn", sizeTeller(arr));
    return 0;
}

int sizeTeller(int array[])
{
    int len;
    return (len = sizeof(array) / sizeof(array[0]));
}
 

Выходной сигнал:

 The number of elements in the array is 2
 

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

Ответ №1:

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

Итак, в случае

 int sizeTeller(int array[])
{
    int len;
    return (len = sizeof(array) / sizeof(array[0]));
}
 

эквивалентно

 int sizeTeller(int* array)
{
    int len;
    return (len = sizeof(array) / sizeof(array[0]));  // sizeof (int *) / sizeof (int)
}
 

Решение: Если вам нужно передать массив в качестве аргумента функции и вам нужно знать его размер, вам нужно вычислить размер в вызывающем объекте и передать его в качестве другого аргумента вызываемой функции.


ПРИМЕЧАНИЕ:

Цитирование C11 , глава 6.3.2.1/P3

За исключением случаев, когда это операнд sizeof оператора, _Alignof оператора или унарного amp; оператора, или строковый литерал, используемый для инициализации массива, выражение, имеющее тип ‘массив типа’, преобразуется в выражение с типом ‘указатель на тип’, который указывает на начальный элемент массиваобъект и не является значением lvalue . [….]

Комментарии:

1. означает ли это, что sizeof(arr) то, что находится в main() , вычисляет размер полного массива. Я имею arr в виду, что это также указатель на первый элемент массива, так почему же он не вернул размер указателя на int , как это было бы сделано в sizeof(int*) .

2. @Neeraj-Kumar-Coder Нет, обратите внимание на часть «как и во многих других случаях», это не «всегда». Я немного расширю ответ, чтобы уточнить.

3. Я понял вашу точку зрения и понял причину неправильного вывода. Но просто объясните мне это, что arr если это указатель на первый элемент массива (как в main() функции), то почему sizeof(arr) не возвращается 8 bytes , что является размером указателя на int .

4. Вы читали последнюю правку? В нем конкретно говорится, что, кроме сценариев, sizeof operator является одним из них.