Стефан Дэвис - С++ для чайников .
- Название:С++ для чайников .
- Автор:
- Жанр:
- Издательство:Издательский дом Вильямс. Компьютерное издательство Диалектика
- Год:2007
- Город:Москва
- ISBN:0-7645-6852-3, 978-5-8459-0723-3
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Стефан Дэвис - С++ для чайников . краткое содержание
1
empty-line
4
С++ для чайников . - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Представим себе, что функция fn( ) начинается с адреса 0x100 , переменная intVar расположена по адресу 0x102, а указатель pintVar — 0x106 ( такое расположение намного проще результатов работы программы Layout ; на самом деле вряд ли переменные будут храниться в памяти именно в таком порядке ).
_________________
108 стр. Часть 2. Становимся функциональными программистами
Первая команда программы сохраняет значение & intVar ( 0x102 ) в указателе pintVar . Вторая строка отвечает за присвоение значения 10 переменной, хранящейся по адресу, который содержится в указателе pintVar ( в нём находится число 0x102, т.е. адрес переменной intVar ).
Сравнение указателей и почтовых адресов...109
Указатели похожи на адреса домов. Ваш дом имеет уникальный адрес, и каждый байт в памяти компьютера тоже имеет уникальный адрес. Почтовый адрес содержит набор цифр и букв. Например, он может выглядеть так: 123 Main Street ( конечно же, это не мой адрес! Я не люблю нашествий поклонников, если только они не женского пола ).
Можно хранить диван в доме по адресу 123 Main Street , и точно так же можно хранить число в памяти по адресу 0x123456. Можно взять лист бумаги и написать на нём адрес — 123 Main Street . Теперь диван хранится в доме, который находится по адресу, написанному на листке бумаги. Так работают сотрудники службы доставки: они доставляют диваны по адресу, который указан в бланке заказа, независимо от того, какой именно адрес записан в бланке ( я ни в коем случае не смеюсь над работниками службы доставки — просто это самый удобный способ объяснить указатели ).
Использовав синтаксис С++, это можно записать так:
House myHouse ;
House* houseAddress ;
houseAddress = & myHouse ;
*houseAddress = couch ;
Эта запись обозначает следующее: myHouse является домом, a houseAddress — адресом дома. Надо записать адрес дома myHouse в указатель houseAddress и доставить диван по адресу, который находится в указателе houseAddress . Теперь используем вместо дома переменную типа int :
int myInt ;
int* intAddress ;
intAddress = & myInt ;
*intAddress = 10 ;
Аналогично предыдущей записи, это поясняется так: myInt — переменная типа int . Следует сохранить адрес myInt в указателе intAddress и записать 10 в переменную, которая находится по адресу, указанному в intAddress .
Использование разных типов указателей...109
Каждое выражение, как и переменная, имеет свой тип и значение. Тип выражения & intVar — указатель на переменную типа int , т.е. это выражение имеет тип int* . При сравнении его с объявлением указателя pintVar становится очевидно, что они одинаковы:
int* pintVar = & intVar ; /* Обе части этого присвоения имеют тип *int */
Аналогично pintVar имеет тип int* , a *pintVar — тип int :
*pintVar = 10 /* Обе части этого присвоения имеют тип int */
Тип переменной, на которую указывает pintVar , — int . Это эквивалентно тому, что если houseAddress является адресом дома, то, как ни странно, houseAddress указывает дом. Указатели на переменные других типов объявляются точно так же:
double doubleVar
double* pdoubleVar = & doubleVar
*pdoubleVar = 10.0
_________________
109 стр. Глава 8. Первое знакомство с указателями в С++
В компьютере класса Pentium размер указателя равен четырём байтам, независимо от того, на переменную какого типа он указывает [ 13 ].
Очень важно следить за соответствием типов указателей. Представьте, что может произойти, если компилятор в точности выполнит такой набор команд:
int n1 ;
int* pintVar ;
pintVar = & n1 ;
*pintVar = 100.0 ;
Последняя строка требует, чтобы по адресу, выделенному под переменную размером в четыре байта, было записано значение, имеющее размер восемь байтов. На самом деле ничего страшного не произойдёт, поскольку в этом случае компилятор приведёт 100.0 к типу int перед тем, как выполнить присвоение.
Привести переменную одного типа к другому явным образом можно так:
int iVar ;
double dVar = 10.0 ;
iVar = ( int )dVar ;
Так же можно привести и указатель одного типа к другому:
int* piVar ;
double dVar = 10.0 ;
double* pdVar ;
piVar = ( int* )pdVar ;
Трудно предсказать, что может случиться, если сохранить переменные одного типа по адресам, выделенным под переменные другого типа. Сохранение переменных, имеющих большую длину, вероятно, приведёт к уничтожению переменных, расположенных рядом. Такая ситуация наглядно продемонстрирована с помощью программы Layout Error :
/* LayoutError — демонстрирует результат неаккуратного обращения с указателями */
#include
#include
#include
using namespace std ;
int main( int intArgc , char* pszArgs[ ] )
{
/* печать кириллицы, если Вы не установите программки gccrus.exe и g++rus.exe */
setlocale ( LC_ALL , ".1251" ) ;
int upper = 0 ;
int n = 0 ;
int lower = 0 ;
/* Вывод адресов каждой из переменных. Обратите внимание на расположение переменных в памяти компьютера */
cout << " & upper = 0x" << & upper<< "\n" ;
cout << " & n = 0x" << & n << "\n" ;
cout << " & lower = 0x" << & lower << "\n" ;
/* Выводим значения объявленных переменных */
cout << "upper = " << upper << "\n" ;
cout << "n = " << n << "\n" ;
cout << "lower = " << lower << "\n" ;
/* Сохраняем значение типа double в памяти, выделенной для int */
cout << "\nСохранение double в int\n\n" ;
cout << "\nСохранение 13.0 по адресу & n\n\n" ;
double* pD = ( double* ) & n ;
*pD = 13.0 ;
/* Показываем результаты */
cout << "upper = " << upper << "\n" ;
cout << "n = " << n << "\n" ;
cout << "lower = " << lower << "\n" ;
/* Пауза для того, чтобы посмотреть на результат работы программы */
system ( "PAUSE" ) ; return 0 ;
}
__________
13Размер указателя зависит не только от типа процессора, но и от операционной системы, используемого компилятора и так называемой модели памяти создаваемой программы. — Прим. ред.
_________________
110 стр. Часть 2. Становимся функциональными программистами
В первых трёх строках функции main( ) происходит объявление трёх переменных типа int . Допустим, что в памяти эти переменные находятся друг за другом.
Следующие три строки выводят значения этих переменных на экран. Не удивительно, что все три оказываются равными нулю. После этого происходит присвоение *pD = 13.0 ; , в результате которого число, имеющее тип double , записывается в переменную n , имеющую тип int . Затем все три переменные снова выводятся на экран.
После записи действительного числа в целочисленную переменную n переменная upper оказалась "забитой" каким-то мусором, что видно из результата работы программы:
Читать дальшеИнтервал:
Закладка: