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



Pdf көрінісі
бет52/256
Дата11.07.2022
өлшемі2,87 Mb.
#37591
1   ...   48   49   50   51   52   53   54   55   ...   256
2.3.2 Неявное преобразование типа 
В присваивании и выражении основные типы могут совершенно свободно использоваться совместно. 
Значения преобразовываются всюду, где это возможно, таким образом, чтобы информация не 
терялась. Точные правила преобразований даны в $$R.4 и $$R.5.4. 
Все-таки есть ситуации, когда информация может быть потеряна или даже искажена. Потенциальным 
источником таких ситуаций становятся присваивания, в которых значение одного типа присваивается 
значению другого типа, причем в представлении последнего используется меньше разрядов. Допустим, 
что следующие присваивания выполняются на машине, в которой целые представляются в 
дополнительном коде, и символ занимает 8 разрядов: 
int i1 = 256+255; 
char ch = i1 
// ch == 255 
int i2 = ch; // i2 == ? 
В присваивании ch=i1 теряется один разряд (и самый важный!), а когда мы присваиваем значение 
переменной i2, у переменной ch значение "все единицы", т.е. 8 единичных разрядов. Но какое значение 
примет i2? На машине DEC VAX, в которой char представляет знаковые значения, это будет -1, а на 
машине Motorola 68K, в которой char - беззнаковый, это будет 255. В С++ нет динамических средств
контроля подобных ситуаций, а контроль на этапе трансляции вообще слишком сложен, поэтому надо 
быть осторожными. 


Бьерн Страуструп.
Язык программирования С++ 
 
52 
2.3.3 Производные типы 
Исходя из основных (и определенных пользователем) типов, можно с помощью следующих операций 
описания: 
* указатель 
& ссылка 
[] массив 
() функция 
а также с помощью определения структур, задать другие, производные типы. Например: 
int* a; 
float v[10]; 
char* p[20]; 
// массив из 20 символьных указателей 
void f(int); 
struct str { short length; char* p; }; 
Правила построения типов с помощью этих операций подробно объяснены в $$R.8. Ключевая идея 
состоит в том, что описание объекта производного типа должно отражать его использование, например: 
int v[10];
// описание вектора 
i = v[3];
// использование элемента вектора 
int* p;
// описание указателя 
i = *p;
// использование указуемого объекта 
Обозначения, используемые для производных типов, достаточно трудны для понимания лишь потому, 
что операции * и & являются префиксными, а [] и () - постфиксными. Поэтому в задании типов, если 
приоритеты операций не отвечают цели, надо ставить скобки. Например, приоритет операции [] выше, 
чем у *, и мы имеем: 
int* v[10];
// массив указателей 
int (*p)[10]; 
// указатель массива 
Большинство людей просто запоминает, как выглядят наиболее часто употребляемые типы. Можно 
описать сразу несколько имен в одном описании. Тогда оно содержит вместо одного имени список 
отделяемых друг от друга запятыми имен. Например, можно так описать две переменные целого типа: 
int x, y;
// int x; int y; 
Когда мы описываем производные типы, не надо забывать, что операции описаний применяются только 
к данному имени (а вовсе не ко всем остальным именам того же описания). Например: 
int* p, y;
// int* p; int y; 
НО НЕ int* y; 
int x, *p;
// int x; int* p; 
int v[10], *p; 
// int v[10]; int* p; 
Но такие описания запутывают программу, и, возможно, их следует избегать. 


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




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

    Басты бет