Способы объявить указатель? - PullRequest
0 голосов
/ 12 декабря 2011

Почему компилируется следующий код:

int main()
{
   int j = 1;
   int *jp = &j;

   cout << "j is " << j << endl;
   cout << "jp is " << jp << endl;
   cout << "*jp is " << *jp << endl;
   cout << "&j is " << &j << endl;
   cout << "&jp is " << &jp << endl;
}

но не это?

#include <iostream>
using namespace std;
int main()
{
   int j = 1;
   int *jp;
   *jp =& j; // This is the only change I have made.
   cout << "j is " << j << endl;
   cout << "jp is " << jp << endl;
   cout << "*jp is " << *jp << endl;
   cout << "&j is " << &j << endl;
   cout << "&jp is " << &jp << endl;
}

Это компилируется, когда я jp = &j, почему? Я только инициализировал jp в другой строке, для меня это не имеет смысла.

Ответы [ 7 ]

6 голосов
/ 12 декабря 2011
int *jp;

jp - указатель. Его значение (jp) является адресом памяти. Это указывает на (*jp) целое число. Когда вы делаете

jp = &j;

Устанавливает значение для адреса памяти j. Так что теперь *jp будет указывать на j. Когда вы делаете

*jp = &j;

Устанавливает значение вещи, jp указывающей на адрес памяти j. Когда вы делаете:

int *jp;
*jp = &j;

jp еще ни на что не указывает - его значение неинициализировано. *jp = &j пытается следовать по адресу памяти значения jp, что является чем-то случайным, и установить его в &j ..., что, вероятно, вызовет ошибку segfault.


Для пояснения: * in (int *jp;) отличается от *jp = .... Первый просто объявляет jp как указатель. Последний определяет, как вы делаете назначение. Чтобы сделать это еще более явным, выполните:

int *jp = &j;

совпадает с

int *jp; jp = &j;

Обратите внимание, что в назначении нет *.

3 голосов
/ 12 декабря 2011
*jp = &j;

Это прямо здесь.Обратите внимание на *.Это идет и получает данные, на которые указывает указатель, аналогично тому, что -> делает для объектов.То, что вы делаете здесь, это присвоение адреса памяти для int.Указатель jp указывает на int, называемый *jp.

Короче говоря, jp - это указатель на int (следовательно, адрес), а *jp - это int, который jpуказывает на.Использование &j дает вам адрес j или указатель на него.

1 голос
/ 12 декабря 2011

Изменить это:

*jp =& j; //this is the only change I have made, 

В это:

jp =& j; 

Это скомпилирует.

Причина, по которой int *jp = &j; компилируется, состоит в том, что она объявляет и , инициализирующие значение. В некомпилируемом коде вы выполняете назначение . И пытается присвоить целочисленное выражение (*jp) указателю один (&j). Что совсем не имеет смысла.

Если вы делаете:

jp = &j;

Затем он скомпилируется, потому что вы присваиваете выражение-указатель (&j) в переменную-указатель (jp). В этом случае есть согласование типов, поэтому имеет смысл компилировать.

0 голосов
/ 12 декабря 2011

Вас сбивает с толку разница между инициализацией и назначением ; две разные вещи.

Линия

int *jp = &j;

объявляет jp как указатель на int, а инициализирует его результатом выражения &j, имеющего тип "pointer to int" (int *).

Линия

*jp = &j;

пытается присвоить результат выражения &j (который имеет тип int *, запомните) результату выражения *jp (который имеет тип int 1 ). Поскольку типов двух выражений не совпадают, вы получаете ошибку во время компиляции.

Обратите внимание, что тот факт, что jp не был инициализирован, чтобы указывать куда-либо значимое, будет ошибкой runtime , а не ошибкой во время компиляции; Итак, если бы вы написали *jp = 5;, программа скомпилировала бы очень хорошо (выражения *jp и 5 имеют совместимые типы), но (скорее всего) взорвалась бы, когда вы попытался запустить его.


1 Объявления в C и C ++ основаны на типах выражений , а не на объектах. Например, мы объявляем jp как указатель на int. Чтобы извлечь значение целого числа, на которое мы указываем, мы разыменовываем указатель с оператором *, как в операторе
x = *jp;  

Тип выражения *jp равен int, поэтому объявление указателя равно

int *jp;  
0 голосов
/ 12 декабря 2011

Вы неправильно разбираете это в своей голове.

Утверждение:

int *jp = &j;

действительно следует читать как:

int* jp = &j;

В результате чего актины:

  • объявить jp как указатель на целое число
  • присвойте значение &j jp

соответствует корректировке вашего второго кодового блока:

   int *jp;
   jp = &j; // This is the only change I have made.
0 голосов
/ 12 декабря 2011

int *jp = &j; объявляет jp как int* (указатель на int) и инициализирует его с &j (адрес j).

*jp = &j разыменовывает указательj (с указанием j), а затем пытается присвоить &j j.Это незаконно, потому что j является int, а &j является int*.

0 голосов
/ 12 декабря 2011

*jp =& j; говорит: «запишите значение &j в местоположение, на которое указывает jp».Это неправильно а) потому что jp ни на что не указывает и б) потому что &j является указателем, а значение, на которое указывает jp, должно быть int, а не указателем.

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