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



Pdf көрінісі
бет55/256
Дата11.07.2022
өлшемі2,87 Mb.
#37591
1   ...   51   52   53   54   55   56   57   58   ...   256
2.3.7 Указатели и массивы 
Указатели и массивы в языке Си++ тесно связаны. Имя массива можно использовать как указатель на 
его первый элемент, поэтому пример с массивом alpha можно записать так: 
int main() 

char alpha[] = "abcdefghijklmnopqrstuvwxyz"; 
char* p = alpha; 
char 
ch; 
while (ch = *p++) 
cout << ch << " = " << int (ch) 
<< " = 0" << oct(ch) << '\n'; 

Можно также задать описание p следующим образом: 
char* p = &alpha[0]; 
Эта эквивалентность широко используется при вызовах функций с параметром-массивом, который 
всегда передается как указатель на его первый элемент. Таким образом, в следующем примере в обоих 
вызовах strlen передается одно и то же значение: 
void f() 

extern "C" int strlen(const char*); // 
из  
char v[] = "Annemarie"; 
char* p = v; 
strlen(p); 
strlen(v); 

Но в том и загвоэдка, что обойти это нельзя: не существует способа так описать функцию, чтобы при ее 
вызове массив v копировался ($$4.6.3). 
Результат применения к указателям арифметических операций +, -, ++ или -- зависит от типа указуемых 


Бьерн Страуструп.
Язык программирования С++ 
 
56 
объектов. Если такая операция применяется к указателю p типа T*, то считается, что p указывает на 
массив объектов типа T. Тогда p+1 обозначает следующий элемент этого массива, а p-1 - предыдущий 
элемент. Отсюда следует, что значение (адрес) p+1 будет на sizeof(T) байтов больше, чем значение p. 
Поэтому в следующей программе 
main() 

char 
cv[10]; 
int 
iv[10]; 
char* pc = cv; 
int* pi = iv; 
cout << "char* " << long(pc+1)-long(pc) << '\n'; 
cout << "int* " << long(pi+1)-long(pi) << '\n'; 

с учетом того, что на машине автора (Maccintosh) символ занимает один байт, а целое - четыре байта, 
получим: 
char* 1 
int* 4 
Перед вычитанием указатели были явной операцией преобразованы к типу long ($$3.2.5). Он 
использовался для преобразования вместо "очевидного" типа int, поскольку в некоторых реализациях 
языка С++ указатель может не поместиться в тип int (т.е. sizeof(int)Вычитание указателей определено только в том случае, когда они оба указывают на один и тот же 
массив (хотя в языке нет возможностей гарантировать этот факт). Результат вычитания одного 
указателя из другого равен числу (целое) элементов массива, находящихся между этими указателями. 
Можно складывать с указателем или вычитать из него значение целого типа; в обоих случаях 
результатом будет указатель. Если получится значение, не являющееся указателем на элемент того же 
массива, на который был настроен исходный указатель (или указателем на следующий за массивом 
элемент), то результат использования такого значения неопределен. Приведем пример: 
void f() 

int 
v1[10]; 
int 
v2[10]; 
int i = &v1[5]-&v1[3]; 
// 2 
i = &v1[5]-&v2[3]; 
// неопределенный результат 
int* p = v2+2; 
// p == &v2[2] 
p = v2-2;
// *p неопределено 

Как правило, сложных арифметических операций с указателями не требуется и лучше всего их 
избегать. Следует сказать, что в большинстве реализаций языка С++ нет контроля над границами 
массивов. Описание массива не является самодостаточным, поскольку необязательно в нем будет 
храниться число элементов массива. Понятие массива в С является, по сути, понятием языка низкого 
уровня. Классы помогают развить его (см. $$1.4.3). 


Достарыңызбен бөлісу:
1   ...   51   52   53   54   55   56   57   58   ...   256




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

    Басты бет