Главная · Поиск книг · Поступления книг · Top 40 · Форумы · Ссылки · Читатели

Настройка текста
Перенос строк


    Прохождения игр    
Aliens Vs Predator |#6| We walk through the tunnels
Aliens Vs Predator |#5| Unexpected meeting
Aliens Vs Predator |#4| Boss fight with the Queen
Aliens Vs Predator |#3| Escaping from the captivity of the xenomorph

Другие игры...


liveinternet.ru: показано число просмотров за 24 часа, посетителей за 24 часа и за сегодня
Rambler's Top100
Образование - Страустрап Б. Весь текст 579.17 Kb

Язык С++

Предыдущая страница Следующая страница
1 ... 3 4 5 6 7 8 9  10 11 12 13 14 15 16 ... 50
      {
          int x;    // прячет первое локальное x
          x = 2;    // присвоить второму локальному x
      }
      x = 3;        // присвоить первому локальному x
  }

  int* p = &x;      // взять адрес глобального x

  Скрытие имен  неизбежно при  написании больших  программ.  Однако
читающий человек  легко  может  не  заметить,  что  имя  скрыто,  и
некоторые  ошибки,   возникающие  вследствие  этого,  очень  трудно
обнаружить, главным  образом потому, что они редкие. Значит скрытие
имен   следует   минимизировать.   Использование   для   глобальных
переменных имен вроде i или x напрашивается на неприятности.
  С помощью  применения операции  разрешения области  видимости  ::
можно использовать скрытое глобальное имя. Например:

  int x;

  f()
  {
      int x = 1;      // скрывает глобальное x
      ::x = 2;        // присваивает глобальному x
  }

  Но возможности использовать скрытое локальное имя нет.
  Область  видимости   имени  начинается   в  точке  описания.  Это
означает,  что   имя  можно   использовать  даже  для  задания  его
собственного значения. Например:

  int x;

  f()
  {
      int x = x;    // извращение
  }

  Это не  является недопустимым,  хотя и бессмысленно, и компилятор
предупредит, что  x "used  before set"  ("использовано до того, как
задано"), если  вы попробуете  так  сделать.  Можно,  напротив,  не
применяя операцию  ::, использовать  одно имя  для  ссылки  на  два
различных объекта в блоке. Например:

                             - стр 50 -

  int x;

  f()             // извращение
  {
      int y = x;  // глобальное x
      int x = 22;
      y = x;      // локальное x
  }

  Переменная y  инициализируется значением  глобального  x,  11,  а
затем ему присваивается значение локальной переменной x, 22.
  Имена параметров  функции считаются  описанными в  самом  внешнем
блоке функции, поэтому

  f(int x)
  {
      int x;        // ошибка
  }

содержит ошибку,  так как  x определено  дважды в  одной и  той  же
области видимости.

     2.1.2 Объекты и Адреса (Lvalue)

  Можно назначать  и использовать  переменные, не  имеющие имен,  и
можно   осуществлять   присваивание   выражениям   странного   вида
(например, *p[a+10]=7).  Следовательно, есть  потребность  в  имени
"нечто  в   памяти".  Вот  соответствующая  цитата  из  справочного
руководства  по   C++:"Объект  есть  область  памяти;  lvalue  есть
выражение,   ссылающееся    на   объект"(#с.5).    Слово   "lvalue"
первоначально было  придумано для значения "нечто, что может стоять
в  левой   части  присваивания".   Однако  не  всякий  адрес  можно
использовать в левой части присваивания; бывают адреса, ссылающиеся
на константу (см. #2.4).

     2.1.3 Время Жизни

  Если программист  не указал  иного, то  объект  создается,  когда
встречается его  описание, и уничтожается, когда его имя выходит из
области  видимости,  Объекты  с  глобальными  именами  создаются  и
инициализируются  один   раз  (только)   и  "живут"  до  завершения
программы.   Объекты,  определенные  описанием  с  ключевым  словом
static, ведут себя так же. Например*:

____________________
* Команда  #include   была выброшена  из примеров  в этой
главе для  экономии места.  Она необходима в примерах, производящих
ввывод, чтобы они были полными. (прим. автора)

                             - стр 51 -

  int a = 1;

  void f()
  {
      int b = 1;          // инициализируется при каждом вызове f()
      static int c = 1;   // инициализируется только один раз
      cout << " a = " << a++
           << " b = " << b++
           << " c = " << c++ << "\n";
  }

  main()
  {
      while (a < 4) f();
  }

производит вывод

  a = 1 b = 1 c = 1
  a = 2 b = 1 c = 2
  a = 3 b = 1 c = 3

  Не инициализированная явно статическая (static) переменная неявно
инициализируется нулем.
  С помощью операций new и delete программист может также создавать
объекты,  время  жизни  которых  управляется  непосредственно;  см.
#3.2.4.

     2.2 Имена

  Имя (идентификатор)  состоит из  последовательности букв  и цифр.
Первый символ  должен быть  буквой.  Символ  подчерка  _  считается
буквой. C++  не налагает  ограничений на число символов в имени, но
некоторые части реализации находятся вне ведения автора компилятора
(в частности,  загрузчик), и  они, к  сожалению, такие  ограничения
налагают.  Некоторые  среды  выполнения  также  делают  необходимым
расширить   или    ограничить   набор    символов,   допустимых   в
идентификаторе;  расширения   (например,  при  допущении  в  именах
символа $)  порождают непереносимые  программы. В качестве имени не
могут использоваться ключевые слова C++ (см. #с.2.3). Примеры имен:

  hello    this_is_a_most_unusially_long_name
  DEFINED  foO    bAr     u_name    HorseSense
  var0     var1   CLASS   _class    ___

  Примеры   последовательностей    символов,   которые   не   могут
использоваться как идентификаторы:

  012      a fool    $sys     class    3var
  pay.due  foo~bar   .name    if

  Буквы в  верхнем и нижнем регистрах считаются различными, поэтому
Count  и   count  -   различные  имена,   но  вводить  имена,  лишь
незначительно отличающиеся  друг  от  друга,  нежелательно.  Имена,
начинающиеся с  подчерка, по  традиции используются для специальных

                             - стр 52 -

средств  среды  выполнения,  поэтому  использовать  такие  имена  в
прикладных программах нежелательно.
  Во время чтения программы компилятор всегда ищет наиболее длинную
строку, составляющую  имя, поэтому  var10 -  это одно имя, а не имя
var, за  которым следует  число 10;  и elseif  -  одно  имя,  а  не
ключевое слово else, после которого стоит ключевое слово if.

     2.3 Типы

  Каждое имя  (идентификатор) в C++ программе имеет ассоциированный
с ним  тип. Этот  тип определяет, какие  операции можно применять к
имени (то  есть к  объекту, на  который оно  ссылается), и  как эти
операции интерпретируются. Например:

  int error number;
  float real(complex* p);

  Поскольку error_number  описано как  int, его  можно присваивать,
использовать в  арифметических выражениях  и т.д. Тогда как функция
real может вызываться с адресом complex в качестве параметра. Можно
взять адрес  любого из  них. Некоторые  имена, вроде int и complex,
являются именами типов. Обычно имя типа используется в описании для
спецификации другого имени. Единственные отличные от этого действия
над именем  типа -  это sizeof  (для определения количества памяти,
которая требуется  для хранения объекта типа) и new (для размещения
объекта типа в свободной памяти). Например:

  main()
  {
      int* p = new int;
      cout << "sizeof(int) = " << sizeof(int) "\n";
  }

  Имя  типа   можно   также   использовать   для   задания   явного
преобразования одного типа в другой, например:

  float f;
  char* p;
  //...
  long ll = long(p);     // преобразует p в long
  int i = int(f);        // преобразует f в int

     2.3.1 Основные Типы

  В C++  есть набор  основных типов, которые соответствуют наиболее
общим основным единицам памяти компьютера и наиболее общим основным
способам их использования:

  char
  short int
  int
  long int

                             - стр 53 -

для представления целых различных размеров,

  float
  double

для представления чисел с плавающей точкой,

  unsigned char
  unsigned short int
  unsigned int
  unsigned long int

для представления  беззнаковых целых,  логических значений, битовых
массивов и  т.п. Для большей компактности записи можно опускать int
в комбинациях  из нескольких  слов, что не меняет смысла; так, long
означает long int, и unsigned означает unsigned int. В общем, когда
в описании опущен тип, он предполагается int. Например:

  const a = 1;
  static x;

все определяют объект типа int.
  Целый тип  char наиболее удобен для хранения и обработки символов
на данном  компьютере; обычно  это 8-битовый байт. Размеры объектов
C++ выражаются  в единицах  размера char,  поэтому  по  определению
sizeof(char)==1. В  зависимости  от  аппаратного  обеспечения  char
является  знаковым   или  беззнаковым  целым.  Тип  unsigned  char,
конечно, всегда  беззнаковый, и  при его  использовании  получаются
более переносимые  программы, но из-за применения его вместо просто
char могут возникать значительные потери в эффективности.
  Причина того, что предоставляется более чем один целый тип, более
чем один беззнаковый тип и более чем один тип с плавающей точкой, в
том,   чтобы    дать   возможность   программисту   воспользоваться
характерными  особенностями   аппаратного  обеспечения.  На  многих
машинах между  различными разновидностями основных типов существуют
значительные различия  в потребностях  памяти, временах  доступа  к
памяти и  временах вычислений.  Зная машину обычно легко, например,
выбрать  подходящий   тип  для   конкретной  переменной.   Написать
действительно переносимую  программу нижнего  уровня  сложнее.  Вот
все, что гарантируется относительно размеров основных типов:
     1==sizeof(char)<=sizeof(short)<= sizeof(int)<=sizeof(long)
     sizeof(float)<=sizeof(double)
Однако обычно  разумно предполагать,  что в  char  могут  храниться
целые числа  в диапазоне  0...127 (в  нем  всегда  могут  храниться
символы машинного  набора символов), что short и int имеют не менее
16 бит,  что int  имеет размер, соответствующий целой арифметике, и
что long  имеет по  меньшей мере  24  бита.  Предполагать  что-либо
помимо этого  рискованно, и даже эти эмпирические правила применимы
не  везде.   Таблицу  характеристик   аппаратного  обеспечения  для
некоторых машин можно найти в #с.2.6.
  Беззнаковые  (unsigned)   целые  типы   идеально   подходят   для
применений, в  которых память  рассматривается  как  массив  битов.
Использование unsigned  вместо int  с тем,  чтобы получить еще один
бит  для   представления  положительных  целых,  почти  никогда  не
оказывается хорошей  идеей. Попытки гарантировать то, что некоторые
значения  положительны,   посредством   описания   переменных   как

                             - стр 54 -

unsigned, обычно  срываются из-за  правил неявного  преобразования.
Например:

  unsigned surprise = -1;

допустимо (но компилятор обязательно сделает предупреждение).

     2.3.2 Неявное Преобразование Типа

  Основные  типы   можно  свободно   сочетать  в   присваиваниях  и
выражениях. Везде,  где это  возможно, значения  преобразуются так,
чтобы информация не терялась. Точные правила можно найти в #с.6.6.
  Существуют  случаи,  в  которых  информация  может  теряться  или
искажаться. Присваивание  значения одного  типа переменной  другого
типа, представление  которого содержит меньшее число бит, неизбежно
является  источником   неприятностей.   Допустим,   например,   что
следующая  часть   программы  выполняется   на  машине  с  двоичным
дополнительным предсталением целых и 8-битовыми символами:

  int i1 = 256+255;
  char ch = i1        // ch == 255
  int i2 = ch;        // i2 == ?

В присваивании  ch=i1 теряется  один бит  (самый значимый!),  и  ch
будет содержать  двоичный код  "все-единицы" (т.е.  8 единиц);  при
присваивании i2  это никак не может превратиться в 511! Но каким же
может быть  значение i2? На DEC VAX, где char знаковые, ответ будет
-1; на AT&T 3B-20, где char беззнаковые, ответ будет 255. В C++ нет
динамического (т.е. действующего во время исполнения) механизма для
разрешения такого  рода проблемм,  а выяснение на стадии компиляции
вообще очень сложно, поэтому программист должен быть внимателен.

     2.3.3 Производные Типы

  Другие  типы   модно  выводить   из  основных   типов  (и  типов,
определенных пользователем) посредством операций описания:

  *     указатель
  &     ссылка
  []    вектор
  ()    функция

и механизма определения структур. Например:
Предыдущая страница Следующая страница
1 ... 3 4 5 6 7 8 9  10 11 12 13 14 15 16 ... 50
Ваша оценка:
Комментарий:
  Подпись:
(Чтобы комментарии всегда подписывались Вашим именем, можете зарегистрироваться в Клубе читателей)
  Сайт:
 
Комментарии (4)

Реклама