Поиск длины массива внутри функции
В программе ниже длина массива ar
правильна в основном, но в temp
она показывает длину указателя на ar
который на моем компьютере равен 2 (в единицах sizeof(int)
).
#include <stdio.h>
void temp(int ar[]) // this could also be declared as 'int *ar'
{
printf("%d\n", (int) sizeof(ar)/sizeof(int));
}
int main(void)
{
int ar[]={1,2,3};
printf("%d\n", (int) sizeof(ar)/sizeof(int));
temp(ar);
return 0;
}
Я хотел бы знать, как я должен определить функцию, поэтому длина массива корректно считывается в функции.
Ответы
Ответ 1
Нет встроенного способа определения длины внутри функции. Однако вы проходите arr
, sizeof(arr)
всегда будет возвращать размер указателя. Поэтому лучший способ - передать количество элементов в качестве отдельного аргумента. В качестве альтернативы вы можете иметь специальное значение, например 0
или -1
которое указывает конец (например, это \0
в строках, которые являются только char []
). Но тогда, конечно, размер "логического" массива был sizeof(arr)/sizeof(int) - 1
Ответ 2
Как говорили другие, очевидным решением является передача длины массива в качестве параметра, также вы можете сохранить это значение в начале массива
#include <stdio.h>
void temp(int *ar)
{
printf("%d\n", ar[-1]);
}
int main(void)
{
int ar[]= {0, 1, 2, 3};
ar[0] = sizeof(ar) / sizeof(ar[0]) - 1;
printf("%d\n", ar[0]);
temp(ar + 1);
return 0;
}
Ответ 3
Не используйте функцию, используйте макрос для этого:
//Adapted from K&R, p.135 of edition 2.
#define arrayLength(array) (sizeof((array))/sizeof((array)[0]))
int main(void)
{
int ar[]={1,2,3};
printf("%d\n", arrayLength(ar));
return 0;
}
Вы все еще не можете использовать этот макрос внутри функции, такой как ваш temp
где массив передается в качестве параметра по причинам, о которых говорили другие.
Альтернативой, если вы хотите передать один тип данных, является определение типа, имеющего как массив, так и емкость:
typedef struct
{
int *values;
int capacity;
} intArray;
void temp(intArray array)
{
printf("%d\n", array.capacity);
}
int main(void)
{
int ar[]= {1, 2, 3};
intArray arr;
arr.values = ar;
arr.capacity = arrayLength(ar);
temp(arr);
return 0;
}
Это занимает больше времени, чтобы настроить, но полезно, если вы обнаружите, что вы пропустили его вокруг многих функций.
Ответ 4
Когда вы пишете size(ar)
вы передаете указатель, а не массив.
Размер указателя и int равен 4 или 8 - в зависимости от ABI (или, как упоминалось в @H2CO3, что-то совершенно другое), поэтому вы получаете sizeof(int *)/sizeof int
(sizeof(int *)/sizeof int
= 1 для 32 -битные машины и 8/4 = 2 для 64-битных машин), который составляет 1 или 2 (или.. что-то другое).
Помните, что в C, когда передать массив в качестве аргумента функции, вы передаете указатель на массив.
Если вы хотите передать размер массива, вы должны передать его как отдельный аргумент.
Ответ 5
Я не думаю, что вы могли бы сделать это, используя функцию. Он всегда будет возвращать длину указателя, а не длину всего массива.
Ответ 6
Внутри функции ar есть указатель, поэтому оператор sizeof возвращает длину указателя. Единственный способ вычислить его - сделать глобальным или изменить его имя. Самый простой способ определить длину - это размер (array_name)/(size_of (int)). Другое, что вы можете сделать, это передать это вычисление в функцию.
Ответ 7
Вам нужно преобразовать массив в структуру:
#include<stdio.h>
struct foo {int arr[5];};
struct bar {double arr[10];};
void temp(struct foo f, struct bar g)
{
printf("%d\n",(sizeof f.arr)/(sizeof f.arr[0]));
printf("%d\n",(sizeof g.arr)/(sizeof g.arr[0]));
}
void main(void)
{
struct foo tmp1 = {{1,2,3,4,5}};
struct bar tmp2;
temp(tmp1,tmp2);
return;
}
Ответ 8
10 марта 2018 г. Редакция:
Код OP вызывает temp() и передает указатель на данные типа int через имя массива, которое по умолчанию относится к arr [0]. Формальный аргумент temp() указывает указатель на данные типа int с обозначением массива, указывающий, что указатель относится к элементу в массиве.
На geeksforgeeks:
Параметры массива [рассматриваются] как указатели из-за эффективности.
Другая статья в geeksforgeeks объясняет, что использование sizeof с указателем означает количество байтов, необходимых для типа данных, а не длину массива. В статье рекомендуется передать дополнительный параметр: фактический размер массива. В этом ключе я создал константу с помощью жесткого кодирования этого значения, как показано в следующем примере:
#define ARR_SIZE 3
#include <stdio.h>
void temp(int arr[], size_t arr_size)
{
int i;
puts ("In temp:");
for (i = 0; i <= arr_size - 1; i++)
{
printf(" %d",arr[i]);
}
puts("\nExiting temp...\n");
}
int main(void)
{
int ar[ARR_SIZE]={1,2,3};
int i=0;
temp(ar,ARR_SIZE);
puts("In main():");
for(i = 0; i < sizeof(ar)/sizeof(ar[i]); i++)
printf(" %d ", ar[i]);
return 0;
}
См. Демонстрацию
Лучшей альтернативой является передача размера массива без жесткого кодирования этого значения. @weston предлагает отличное предложение относительно кодирования функционально-подобного макроса для определения длины массива. Хотя вы не можете использовать макрос внутри тела функции temp(), вы можете использовать макрос для передачи данных в temp(), как показано ниже:
#define array_len(array) sizeof(array)/sizeof(array[0])
#include <stdio.h>
void temp(int arr[], size_t arr_size)
{
int i;
printf("\nArray size is: %d\nValues are:\n", (int) arr_size);
for (i = 0; i <= arr_size - 1; i++)
{
printf(" %d",arr[i]);
}
}
int main(void)
{
int ar[]={1,2,3};
int i=0;
temp( ar, array_len(ar) );
return 0;
}
Просмотреть код в реальном времени
Интересная связанная дискуссия и хорошее чтение о макросах здесь.