4.8. Аргумент - масив
Масивите в С++
никога не се изпращат по стойност. По-скоро масивът се подава чрез указател към
първия му елемент. Например,
void putValues( int[ 10 ] )]
се
разглежда от компилатора сякаш е било декларирано като
void putValues(
int* );
Безсмислено е да се декларира размера на масив, когато се подава
като формален аргумент. Следните три декларации са еквивалентни
// three
equivalent declarations of putValues
void putValues( int* );
void
putValues( int[] );
void putValues( int[ 10 ] );
За програмиста това
означава следните две неща
Промените на аргумента - масив в извиканата
функция са направени над фактическия масив на обръщението, а не над локалното
копие. В случаите, когато масивът на обръщението трябва да остане непроменен, е
необходимо програмистът сам да симулира изпращане по стойност.
Размерът
на масива не е част от типа на аргумента. Функцията, която има аргумент масив не
знае неговият фактически размер;
това важи и за компилатора. Няма
проверка за размера на масива. Например,
void putValues( int[ 10 ] ); //
treated as int*
main() {
int i, j[ 2 ];
putValues( &i ); //
ok
int*;
run-time error putValues( j ); // ok
int*;
run-time error
return 0;
}
Проверката на типа на аргумента просто потвърждава, че
двете обръщения към putValues() са с аргумент от тип int*.
Съществува
споразумение, че низов масив от символи се ограничава с нулев символ. Всички
останали типове на масиви, обаче, включително символните масиви, които желаем да
обработим с вмъкнатите нулеви символи, трябва да указват по някакъв начин
размера си, когато бъдат изпращани като формални аргументи на функции. Един общ
метод е да използуваме допълнителен аргумент, който съдържа размера на
масива.
void petValues9 ( int[], int size );
main() {
int i,
j[ 2 ];
putValeus( i, 1 );
putValues( j, 2 );
return 0;}
putValues()
отпечатва стойностите на масива в следния формат
( 10 ) < 0, 1, 2, 3,
4, 5, 6, 7, 8, 9 >
където 10 представлява размера на масива. Ето една
реализация
#include <stream.h>
const lineLength = 12; //
elements to a line
void putValues( int *ia, int sz ) {
cout << "("
<< sz; ") <";
for ( int i = 0; i < sz; ++i )
{
if ( i %
lineLength == 0 && i ) {
cout << "nt"; // line filled
cout
<< ia[ i ]; // seperate all but last element
if ( i % lineLength !=
lineLength-1 &&i != sz - 1 ) {
cout << ", ";
}
cout
<< " >n";
}
Многомерните масиви, декларирани като формални
аргументи, трябва да определят всички свои размерности след първата.
Например,
void putValues( int matrix[][10], int rowSise
);
декларира matrix като двумерен масив. Всеки ред на matrix се състои от
10 елемента. Една еквивалентна декларация на matrix има вида
int
(*matrix) [10];
Това декларира matrix като указател към масив от 10
елемента.
matrix += 1;
ще увеличи matrix с размера на втората му
размерност и ще го насочи към следващия му ред - ето защо трябва да бъде
поддържана следващата размерност. Заграждането на matrix в скоби е необходимо,
защото индексният оператор има по-висок приоритет.
int *matrix[ 10
];
декларира matrix като масив от десет указателя към цели
числа.