Почему размер параметра массива не такой же, как в main?

Почему размер массива, отправляемого в качестве параметра, не такой же, как в main?

#include <stdio.h>

void PrintSize(int p_someArray[10]);

int main () {
    int myArray[10];
    printf("%d\n", sizeof(myArray)); /* As expected, 40 */
    PrintSize(myArray);/* Prints 4, not 40 */
}

void PrintSize(int p_someArray[10]){
    printf("%d\n", sizeof(p_someArray));
}

13 ответов

Решение

Тип массива неявно преобразуется в тип указателя при передаче его функции.

Так,

void PrintSize(int p_someArray[10]) {
    printf("%zu\n", sizeof(p_someArray));
}

а также

void PrintSize(int *p_someArray) {
    printf("%zu\n", sizeof(p_someArray));
}

эквивалентны. Так что вы получаете это значение sizeof(int*)

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

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

#include <stdio.h>

void PrintSize1 ( int someArray[][10] );
void PrintSize2 ( int someArray[10] );

int main ()
{
    int myArray[10];
    printf ( "%d\n", sizeof myArray ); /* as expected 40 */
    printf ( "%d\n", sizeof ( int[10] ) ); /* requires parens */
    PrintSize1 ( 0 ); /* prints 40, does not evaluate 0[0] */
    PrintSize2 ( 0 ); /* prints 40, someArray unused */
}

void PrintSize1 ( int someArray[][10] )
{
    printf ( "%d\n", sizeof someArray[0] );
}

void PrintSize2 ( int someArray[10] )
{
    printf ( "%d\n", sizeof ( int[10] ) );
}

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

K & R на помощь:

#define N_ELEMENTS(array) (sizeof(array)/sizeof((array)[0])) 

Так что теперь вы можете сделать, например:

int a[10];
...
myfunction(a, N_ELEMENTS(a));

Поведение, которое вы обнаружили, на самом деле большая бородавка на языке Си. Всякий раз, когда вы объявляете функцию, которая принимает параметр массива, компилятор игнорирует вас и изменяет параметр на указатель. Таким образом, эти объявления ведут себя как первый:

void func(int *a)
void func(int a[])
void func(int a
typedef int array_plz[5];
void func(array_plz a)

a будет указателем на int во всех четырех случаях. Если вы передадите массив в func, он сразу же превратится в указатель на свой первый элемент. (В 64-битной системе 64-битный указатель в два раза больше 32-битного целого, поэтому соотношение sizeof возвращает 2.)

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

Это не означает, что невозможно передать массив функции. Вы можете обойти эту бородавку, встроив массив в структуру (это в основном цель std:: array в C++11):

struct array_rly {
int a[5];
};
void func(struct array_rly a)
{
printf("%zd\n", sizeof(a.a)/sizeof(a.a[0]));  /* prints 5 */
}

или передав указатель на массив:

void func(const int (*a)[5])
{
printf("%zd\n", sizeof(*a)/sizeof((*a)[0]));  /* prints 5 */
}

Если размер массива не является константой времени компиляции, вы можете использовать технику указателя на массив с массивами переменной длины C99:

void func(int n, const int (*a)[n])
{
printf("%zd\n", sizeof(*a)/sizeof((*a)[0]));  /* prints n */
}

В C++ вы можете передать массив по ссылке для этой цели:

void foo(int (&array)[10])
{
    std::cout << sizeof(array) << "\n";
}

Потому что массивы распадаются на указатели, когда они передаются как параметры. Вот как работает C, хотя вы можете передать "массивы" в C++ по ссылке и преодолеть эту проблему. Обратите внимание, что вы можете передавать массивы разных размеров в эту функцию:

 // 10 is superfluous here! You can pass an array of different size!
void PrintSize(int p_someArray[10]);

В языке Си нет способа определить размер неизвестного массива, поэтому необходимо передать количество, а также указатель на первый элемент.

Вы не можете передавать массивы в функции.

Если вы действительно хотите напечатать размер, вы можете передать указатель на массив, но он не будет универсальным, поскольку вам также необходимо определить размер массива для функции.

#include <stdio.h>

void PrintSize(int (*p_anArray)[10]);

int main(void) {
    int myArray[10];
    printf("%d\n", sizeof(myArray)); /* as expected 40 */
    PrintSize(&myArray);/* prints 40 */
}

void PrintSize(int (*p_anArray)[10]){
    printf("%d\n", (int) sizeof(*p_anArray));
}

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

fun(int a[]) похожа на fun(int *a);

поэтому, когда вы печатаете размер массива, он печатает размер первого элемента.

Поведение - это дизайн.

Тот же синтаксис в объявлении параметров функции означает совершенно другое, чем в определении локальной переменной.

Причина описана в других ответах.

В "C" программировании язык "sizeof ()" является оператором, и он возвращает размер объекта в байтах. Аргументом оператора "sizeof ()" должен быть тип левого значения (целое число, число с плавающей запятой, структура, массив).). Так что если вы хотите узнать размер массива в байтах, вы можете сделать это очень просто. Просто используйте оператор sizeof () и в качестве аргумента используйте имя массива. Например:

#include <stdio.h>

main(){

 int n[10];
 printf("Size of n is: %d \n", sizeof(n)); 

}

Выход в 32-битной системе будет иметь следующий размер: Размер n равен: 40. Потому что в 32-разрядной системе Integer равен 4 байта. В 64x это 8 байтов. В этом случае у нас есть 10 целых чисел, объявленных в одном массиве. Таким образом, результат равен '10 * sizeof(целое).

Несколько советов:

Если у нас есть массив, объявленный как этот 'int n[]={1, 2, 3, ...155..};'. Итак, мы хотим знать, сколько элементов хранится в этом массиве. Используйте этот алгоритм:

sizeof (name_of_the_array) / sizeof (array_type)

Код: #include

главный(){

int n[] = { 1, 2, 3, 44, 6, 7 };
printf("Number of elements: %d \n", sizeof(n) / sizeof(int));
return 0;

}

Массивы имеют только свободный размер. По большей части массив является указателем на память. Размер в вашем объявлении только указывает компилятору, сколько памяти выделить для массива - он не связан с типом, поэтому sizeof() не имеет ничего общего.

Другие вопросы по тегам