Бьерн Страуструп. Язык программирования С++ Второе дополненное издание



Pdf көрінісі
бет91/256
Дата11.07.2022
өлшемі2,87 Mb.
#37591
1   ...   87   88   89   90   91   92   93   94   ...   256
4.6.5 Параметр-массив 
Если в качестве параметра функции указан массив, то передается указатель на его первый элемент. 
Например: 
int strlen(const char*); 
void f() 

char v[] = "
массив"; 
strlen(v); 
strlen("
Николай"); 

Это означает, что фактический параметр типа T[] преобразуется к типу T*, и затем передается. Поэтому 
присваивание элементу формального параметра-массива изменяет этот элемент. Иными словами, 
массивы отличаются от других типов тем, что они не передаются и не могут передаваться по значению. 
В вызываемой функции размер передаваемого массива неизвестен. Это неприятно, но есть несколько 
способов обойти данную трудность. Прежде всего, все строки оканчиваются нулевым символом, и 
значит их размер легко вычислить. Можно передавать еще один параметр, задающий размер массива. 
Другой способ: определить структуру, содержащую указатель на массив и размер массива, и 
передавать ее как параметр (см. также $$1.2.5). Например: 
void compute1(int* vec_ptr, int vec_size); // 1-
ый способ 
struct vec { 
// 2-
ой способ 
int* 
ptr; 
int 
size; 
}; 
void compute2(vec v); 
Сложнее с многомерными массивами, но часто вместо них можно использовать массив указателей, 
сведя эти случаи к одномерным массивам. Например: 
char* day[] = { 
"mon", "tue", "wed", "thu", "fri", "sat", "sun" 
}; 
Теперь рассмотрим функцию, работающую с двумерным массивом - матрицей. Если размеры обоих 
индексов известны на этапе трансляции, то проблем нет: 
void print_m34(int m[3][4]) 

for (int i = 0; i<3; i++) { 
for (int j = 0; j<4; J++) 
cout << ' ' << m[i][j]; 
cout 
<< 
'\n'; 


Конечно, матрица по-прежнему передается как указатель, а размерностиприведены просто для полноты 
описания. 
Первая размерность для вычисления адреса элемента неважна($$R.8.2.4), поэтому ее можно 
передавать как параметр: 
void print_mi4(int m[][4], int dim1) 


Бьерн Страуструп.
Язык программирования С++ 
 
111 

for ( int i = 0; ifor ( int j = 0; j<4; j++) 
cout << ' ' << m[i][j]; 
cout << '\n'; 


Самый сложный случай - когда надо передавать обе размерности. Здесь "очевидное" решение просто 
непригодно: 
void print_mij(int m[][], int dim1, int dim2) // 
ошибка 

for ( int i = 0; ifor ( int j = 0; jcout << ' ' << m[i][j]; 
cout 
<< 
'\n'; 


Во-первых, описание параметра m[][] недопустимо, поскольку для вычисления адреса элемента 
многомерного массива нужно знать вторую размерность. Во-вторых, выражение m[i][j] вычисляется как 
*(*(m+i)+j), а это, по всей видимости, не то, что имел в виду программист. Приведем правильное 
решение: 
void print_mij(int** m, int dim1, int dim2) 

for (int i = 0; i< dim1; i++) { 
for (int j = 0; jcout << ' ' << ((int*)m)[i*dim2+j]; // 
запутано 
cout 
<< 
'\n'; 


Выражение, используемое для выбора элемента матрицы, эквивалентно тому, которое создает для 
этой же цели транслятор, когда известна последняя размерность. Можно ввести дополнительную 
переменную, чтобы это выражение стало понятнее: 
int* v = (int*)m; 
// ... 
v[i*dim2+j] 
Лучше такие достаточно запутанные места в программе упрятывать. Можно определить тип 
многомерного массива с соответствующей операцией индексирования. Тогда пользователь может и не 
знать, как размещаются данные в массиве (см. упражнение 18 в $$7.13). 


Достарыңызбен бөлісу:
1   ...   87   88   89   90   91   92   93   94   ...   256




©emirsaba.org 2024
әкімшілігінің қараңыз

    Басты бет