2011-02-10 3 views
0

В следующей программе С:просчет размера массива внутри функции

int doStuff(int afm[]); 

int main(){ 
    int afm1[9] = {1,2,3,4,5,6,7,8,9}; //size=9 

    int afmLength = sizeof(afm1)/sizeof(int); 
    printf("main: Length Of Array=%d\n", afmLength); //9 OK 

    int k = doStuff(afm1); 

    system("PAUSE"); 
    return 0; 
} 

int doStuff(int afm[]){ 
    int afmLength = sizeof(afm)/sizeof(int);  
    printf("doStuff: Length Of Array=%d\n", afmLength); //1 WRONG 

    return 1; 
} 

производит следующий вывод:

main: Length Of Array=9 
doStuff: Length Of Array=1 

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

ответ

7

Поскольку в main у вас есть массив, а в функции у вас есть указатель на этот массив.

int doStuff(int afm[]) 

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

int doStuff(int *afm) 
+0

Спасибо Давиду. Что я должен писать вместо этого? – athspk

+1

Ответ Арготе говорит вам. Функция 'doStuff' не имеет информации о длине массива. Вам нужно будет передать эту информацию в функцию вместе с указателем на массив. –

2

Добавление ответа Дэвида Хеффернэн (который является правильным), вы должны иметь еще один параметр, который будет длина массива передается на ваш метод doStuff.

+0

+1 Я меняю «размер» на «длину», потому что более нормально работать с длинами, чем размеры (я уверен, что это то, что вы имели в виду). –

+0

Да, Давид, спасибо. – Argote

0

От стандарта языка C (проект n1256):

6.3.2.1 Lvalues, массивы и функции десигнаторами
...
3 исключением случаев, когда это операнд оператора sizeof или унарный оператор & или строковый литерал , используемый для инициализации массива, выражение, которое имеет массив типа '' из , тип '' - это , преобразованный в выражение с указателем типа '' to тип '', который указывает на исходный элемент объекта массива и не является значением lvalue. Если объект массива имеет класс хранения регистров, поведение не определено.

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

При вызове doStuff(afm1);, выражение afm1 неявно преобразуется из типа «9-элементный массив int» в «указатель на int», а значение выражения такой же, как &afm1[0]. Так что doStuff получает значение указателя, а не массив.

В контексте декларации параметров функции, T a[] и T a[N] оба интерпретируются как T *a:

6.7.5.3 Функция declarators (в том числе прототипов)
...
7 Декларации параметр как '' массив из типа '' должен быть скорректирован на '' квалифицированный указатель на тип '', где квалификаторы типа (если есть) в пунктах [ и ] из .Если ключевое слово static также появляется в [ и ] типа деления типа массива , то для каждого вызова функции значение соответствующего фактического аргумента должно обеспечивать доступ к первому элементу массива, по меньшей мере, столько же элементы, указанные выражением размера.

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

Так что, когда вы звоните doStuff из main, вам нужно сделать что-то вроде

doStuff(afm1, sizeof afm1/sizeof *afm1); 
... 
int doStuff(int *afm, size_t afmsize) 
{ 
    ... 
} 
Смежные вопросы