Почему размер параметра массива не такой же, как в 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() не имеет ничего общего.