C размер переданного массива
Возможный дубликат:
Как найти sizeof (указатель, указывающий на массив)
Я понимаю, что оператор sizeof оценивается и заменяется константой во время компиляции. Учитывая, что может ли функция, передаваемая разными массивами в разных точках программы, вычислить ее размер? Я могу передать его как параметр функции, но мне не нужно добавлять другой параметр, если мне не обязательно.
Вот пример, иллюстрирующий то, что я прошу:
#include <stdio.h>
#include <stdlib.h>
#define SIZEOF(a) ( sizeof a / sizeof a[0] )
void printarray( double x[], int );
int main()
{
double array1[ 100 ];
printf( "The size of array1 = %ld.\n", SIZEOF( array1 ));
printf( "The size of array1 = %ld.\n", sizeof array1 );
printf( "The size of array1[0] = %ld.\n\n", sizeof array1[0] );
printarray( array1, SIZEOF( array1 ) );
return EXIT_SUCCESS;
}
void printarray( double p[], int s )
{
int i;
// THIS IS WHAT DOESN"T WORK, SO AS A CONSEQUENCE, I PASS THE
// SIZE IN AS A SECOND PARAMETER, WHICH I'D RATHER NOT DO.
printf( "The size of p calculated = %ld.\n", SIZEOF( p ));
printf( "The size of p = %ld.\n", sizeof p );
printf( "The size of p[0] = %ld.\n", sizeof p[0] );
for( i = 0; i < s; i++ )
printf( "Eelement %d = %lf.\n", i, p[i] );
return;
}
Ответы
Ответ 1
Нет волшебного решения. C не является отражающим языком. Объекты автоматически не знают, что они собой представляют.
Но у вас есть много вариантов:
- Очевидно, добавьте параметр
- Оберните вызов макросом и автоматически добавьте параметр
- Используйте более сложный объект. Определите структуру, которая содержит динамический массив, а также размер массива. Затем передайте адрес структуры.
Ответ 2
Функциональные параметры никогда не имеют типа массива. Когда компилятор видит
void printarray( double p[], int s )
или даже
void printarray( double p[100], int s )
он преобразует либо один в
void printarray( double* p, int s )
Итак, sizeof(p)
- sizeof(double*)
. И да, вам придется передать размер в качестве параметра.
Ответ 3
Проблема в том, что ваша функция не получает значение массива; он получает значение указателя.
За исключением случаев, когда это операнд операторов sizeof
или унарных &
, или это строковый литерал, используемый для инициализации другого массива в объявлении, выражение типа "массив из T
" будет преобразованный в тип "указатель на T
", и его значение будет адресом первого элемента массива.
Таким образом, когда вы вызываете printarray
, тип array1
неявно преобразуется из "100-элементного массива double
" в "указатель на double
". Таким образом, тип параметра p
равен double *
, а не double [100]
.
В контексте объявления параметра функции T a[]
идентичен T *a
.
Вот почему вы должны передавать размер массива отдельно;
Ответ 4
Вы можете использовать значение контрольной суммы, с которой связаны строки. Недостатком является то, что вам нужно перебирать весь массив, чтобы найти его размер.
Например, когда у вас есть строка, например:
char s1[] = "foobar";
На самом деле у вас есть массив длиной 7, причем седьмое пятно является нулевым завершающим char '\ 0', которое служит для обозначения конца массива/строки.
Другой способ сделать это - создать структуру, состоящую из размера, за которым следует массив.
Ответ 5
Вы ответили на свой вопрос. Он вычислялся во время компиляции, так как же "sizeof p" может иметь более одного значения во время выполнения?
Передача длины в качестве параметра является прекрасным решением, в противном случае вы можете убедиться, что ваши массивы всегда заканчиваются некоторым специальным значением (например, строками и нулевым байтом).
Ответ 6
Вы должны либо
- Передайте размер массива в качестве параметра функции
- Убедитесь, что массив заканчивается известным значением и останавливается, когда вы достигаете этого значения.
Ответ 7
Если ваш массив имеет нулевой конец, вы можете выполнить итерацию по массиву и найти последнее значение. Многие строковые операторы в C работают таким образом
В противном случае у вас нет выбора.
sizeof вернет размер p, который является указателем и будет равен вашему размеру int