#c
Вопрос:
Что это такое?
1)
CCamera amp;MyCamera = *(CCamera *)0xB6F028;
Мы получаем адрес переменной: 0xB6F028, вводим его в CCamera* и разыменовываем.
И инициализируйте ссылку CCamera. Что? Как это работает?
Разыменовав, мы получим значение этого адреса. И это значение присваивается ссылке?
2)
CPool<CVehicle, CHeli> *amp;CPools::ms_pVehiclePool =*(CPool<CVehicle, CHeli> **)0xB74494;
Это у нас есть ссылка COOL на указатель.
И у нас есть адрес указателя для начала этого класса.
Далее мы наберем адрес указателя на указатель на указатель на CPool следующим образом: (CPool**)0xB74494.
А затем мы разыменуем это и получим значение 0xB74494. Это значение — указатель на начальный CPool — это адрес начального CPool в памяти.
Ну, это адреса в памяти: 0xB74494 значение хранилища: 0xAddressOfCPool
Что случилось? Почему мы снова присваиваем значение var ссылке на указатель?
Мы снова присваиваем значение var.
Как это работает?
Комментарии:
1. Этот трюк, возможно, вызывает неопределенное поведение (UB), но мне интересно! А может быть, у нас есть книга, в которой описываются эти трюки? Пожалуйста, дайте мне знать
2.
(CCamera *)
является явным преобразованием типа. Это в значительной степени слово Божье для составителя. Независимо от того, насколько глупо то, что вы собираетесь сделать на самом деле, компилятор позволит это, не задавая вопросов. Это означает, что если у вас нет допустимогоCCamera
значения 0xB6F028, вам придется удалить <удалено ругательство>, как только вы попытаетесь использовать эту ссылку.3. Обычно вы делаете такие вещи в программировании очень низкого уровня, где вы напрямую взаимодействуете с оборудованием. Компилятор никак не может знать, что у вас действительно есть доступное устройство по этому адресу, но поскольку вы прочитали руководство по устройству, вы знаете, что оно там есть, и можете заставить компилятор принять его.
4. @user4581301 хорошо, мы наберем этот адрес на указатель. Но почему мы разыменовываем его? Путем разыменования мы получаем значение этого адреса, но почему? Ссылка, инициализированная значением var в памяти?
5. «Разыменование» существует только потому
MyCamera
, что илиms_pVehiclePool
определены как ссылки и не указатели. Ссылка технически является указателем (адресом), но семантика такова, как если бы она была объектом.MyCamera
переменная будет содержать адрес0xB6F028
.
Ответ №1:
Разыменовав, мы получим значение этого адреса. И это значение присваивается ссылке?
Вы не можете назначить ссылку. Вы можете инициализировать только ссылку.
Теперь подумайте об этом:
int x = 42;
intamp; rx = x; // initialises rx to refer to x
Пока все так хорошо? Давайте продолжим.
intamp; rx = *(amp;x); // still initialises rx to refer to x
// because *(amp;x) is exactly the same as just x
Никаких проблем с этим? Тогда в чем *(CCamera *)0xB6F028;
проблема?
Когда вы разыменовываете указатель, какой результат вы получаете? Понимает ли *(amp;x)
тебя 42
?
Не совсем. Вы получаете значение glvalue. Значение glvalue определяет идентичность объекта. И когда вы инициализируете ссылку значением glvalue, эта ссылка начинает ссылаться на этот объект. Когда вы выполняете большинство других действий с значением glvalue, оно автоматически преобразуется в значение prvalue, которое в данном случае действительно равно 42. Но инициализация ссылки не относится к числу таких вещей.
Так что же происходит, когда вы разыменовываете (CCamera *)0xB6F028;
? Вы получаете значение glvalue, которое является идентификатором объекта, который находится по адресу 0xB6F028
и тип которого CCamera
. И вы инициализируете ссылку этим. Таким образом, ссылка теперь относится к объекту, находящемуся по этому адресу.
Если CCamera
по этому адресу действительно есть «а», вы молодец. В противном случае попытка разыменования этого указателя будет UB.
CPool<CVehicle, CHeli> *amp;CPools::ms_pVehiclePool =*(CPool<CVehicle, CHeli> **)0xB74494;
То же самое, только тип объекта теперь является указателем, и ссылка ссылается на этот указатель. Указатель-это просто совершенно обычный объект, так что здесь не происходит ничего особенного.