О reinterpret_cast и указатель - PullRequest
       1

О reinterpret_cast и указатель

0 голосов
/ 18 сентября 2018

Я изучаю C и C ++.В этой программе:

#include <iostream>

int main() {

    const int g = 10;
    int * k = reinterpret_cast <int *> (20000); //ok
    std::cout << "k : " << k  << std::endl;
    std::cout << "* k : " << * k << std::endl;

    * k = g;
    std::cout << "* k : " << *k << std::endl;

    return 0;
}

. / ConverForTyEn
k: 0x4e20 Ошибка сегментации (ядро сброшено)

Я ожидаю 20000, а затем 10. Но кажется, что ошибка "означает"что вы пытались получить доступ к памяти, к которой у вас нет доступа. "(Эрси Финн).Спасибо за помощь.

Ответы [ 3 ]

0 голосов
/ 18 сентября 2018

Ваш код вызывает неопределенное поведение (UB), и вероятный вывод будет:

k : 0x4e20
Segmentation fault

где первая строка - адрес k. Затем в этой строке кода:

std::cout << "* k : " << * k << std::endl;

вы пытаетесь получить доступ к этому адресу, который находится вне сегмента вашей программы, что вызывает ошибку сегментации.

0 голосов
/ 18 сентября 2018

В рабочем проекте стандарта (N4713) говорится об использовании

8.5.1.10 Повторное толкование акта
...
5. Значение целочисленного типа или типа перечисления может быть явно преобразовано в указатель .Указатель, преобразованный в целое число достаточного размера (если таковое существует в реализации) и обратно в тот же тип указателя, будет иметь свое первоначальное значение;Отображения между указателями и целыми числами определяются реализацией.[Примечание: За исключением случаев, описанных в 6.6.4.4.3, результатом такого преобразования не будет безопасно полученное значение указателя .—Конец примечания]

И:

6.6.4.4.3 Безопасно полученные указатели [basic.stc.dynamic.safety]
...
2. Значение указателя является надежно полученным указателем на динамический объект, только если он имеет тип указателя объекта и является одним из следующих :
(2.1)- значение, возвращаемое вызовом реализации стандартной библиотеки C ++ :: operator new (std :: size_t) или :: operator new (std :: size_t, std :: align_val_t);
(2.2) - результатвзятия адреса объекта (или одного из его подобъектов), обозначенного lvalue, являющимся результатом косвенного обращения через безопасно полученное значение указателя;
(2.3) - результат хорошо определенной арифметики указателя с использованием безопасно полученного указателяvalue;
(2.4) - результат четко определенного преобразования указателя в безопасно полученное значение указателя;
(2.5) - результат reinterpret_cast из безопасно полученного значения указателя;
(2.6) - результат reinterpret_cast целочисленного повторенияпредставление значения безопасно полученного указателя;

(2.7) - значение объекта, значение которого было скопировано из прослеживаемого объекта указателя, где во время копирования исходный объект содержал копию безопаснополученное значение указателя.

Поскольку вы используете reinterpret_cast для целочисленного литерала (20000), результатом преобразования будет , а не безопасно полученное значение указателя.Попытка разыменования такого значения указателя приводит к неопределенному поведению.

0 голосов
/ 18 сентября 2018

Указатель должен указывать на действительную память, которая будет использоваться. В вашем случае вы устанавливаете его на произвольную ячейку памяти, 20000.

Примером правильного использования указателя будет

int x = 42;
int *px = &x;

Это помещает адрес x в px.

std::cout << px;

Будет выводить адрес.

std::cout << *px;

Выведет значение x.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...