понимание инициализации указателя в C ++ - PullRequest
0 голосов
/ 27 мая 2018

Привет сообщество stackoverflow, я изучал указатели в C ++.Я немного разбираюсь в golang и python, но не в C или C ++, так что простите меня из-за моего неправильного понимания.Позвольте мне опубликовать кусок кода, который работает нормально и дает segfault.

  • 1

Этот печатает 5

int var = 5;
int *p = &var;
cout << *p << endl;
  • 2

Этот также печатает 5

int *p;
p = &var;
cout << *p << endl;

печатает 5 (потому что p - указатель на int, а адрес var - указатель на int.).

Однако,

  • 3

Этот segfaults.

int *p;
*p = var;
cout << *p << endl;

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

и

  • 4

Этот также segfaults

int *p;
*p = 5;
cout << *p << endl;

также генерирует segfault.Насколько я понимаю для приведенного выше кода, я объявил указатель на int, и я присваиваю целочисленное значение разыменованному указателю на целое число, но поскольку переменная не инициализирована, компилятор не назначил память в стекедля хранения значения (что-то вроде поведения висячего указателя?) Если это причина, почему она выдает ошибку сегментации, причиной этой ошибки является доступ к памяти вне досягаемости программы?

  • Еслипеременная объявляется только и не инициализируется, компилятор полностью игнорирует имя переменной и рассматривает его как несуществующее имя переменной?

Спасибо.

Ответы [ 3 ]

0 голосов
/ 27 мая 2018

Когда вы создаете указатель, он содержит какой-то мусорный адрес.Когда вы пытались разыменовать это и записывать какое-то значение, вы вызывали неопределенное поведение.Вы должны назначить адрес некоторой существующей переменной в стеке или выделить память в куче, а затем вы можете разыменовать ее.
Как вы делали в первых 2 примерах.Вы также можете выделить некоторую память в куче и назначить адрес этой памяти вашему указателю.
int *ptr = new int;
Теперь вы можете разыменовать этот указатель (при условии, что исключение bad_alloc не было выброшено), и назначить значение дляпамять указанная указателем.

0 голосов
/ 27 мая 2018

В последнем вы написали:

int *p;
*p = 5;
cout << *p << endl;

Но в этом случае вы не присвоили значение p.Вы должны присвоить значение указателю, прежде чем использовать его.Вы можете попробовать следующим образом:

int *p;
p = &var; //or another address of integer variable
*p = 5;
cout << *p << endl;

, я хочу подчеркнуть, что вы должны присвоить значение указателю перед его использованием.

0 голосов
/ 27 мая 2018

Почему во время компиляции не отображалась ошибка несовместимого типа, а не возникала ошибка сегментации?

Поскольку типы совместимы.*p имеет тип int, var также имеет тип int.Здесь вы имеете дело с проблемой во время выполнения, а не во время компиляции.

Что пытается сделать программа, которая выдает ошибку сегментации, и как?

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

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

Если переменная объявлена ​​только и не инициализирована, компилятор полностью игнорирует имя переменной и обрабатывает его как неимя существующей переменной?

Совсем нет.Объявление вводит имя в определенную область.В ваших примерах у вас было определений : они сказали компилятору выделить им определенное количество места.

...