Подтвердить что ты не робот

Указатели: инициализация против объявления

Я С++ noob, и я уверен, что это глупый вопрос, но я просто не совсем понимаю, почему возникает ошибка (не возникает) из следующего кода:

#include <iostream>
using namespace std;


int main() 
{
int a,*test; 

*test = &a;  // this error is clear to me, since an address cannot be 
             // asigned to an integer  


*(test = &a); // this works, which is also clear
return 0;
}

Но почему это тоже работает?

#include <iostream>
using namespace std;

int main() 
{
int a, *test= &a;  // Why no error here?, is this to be read as:
                   // *(test=&a),too? If this is the case, why is the 
                   // priority of * here lower than in the code above?

return 0;
}
4b9b3361

Ответ 1

Основное различие между этими двумя строками

*test= &a; // 1
int a, *test= &a; // 2

- это первое выражение, состоящее из вызовов операторов с известными правилами приоритета:

       operator=
          /\
        /    \
      /        \
operator*    operator&
  |             | 
 test           a

тогда как второе - объявление переменной и инициализация и эквивалентно объявлению int a;, за которым следуют:

   int*     test    =  &a
// ^^        ^^        ^^
//type    variable    expression giving
//          name        initial value

Ни во время operator*, ни operator= не используется во второй строке.

Значение токенов * и =&, а также ,) зависит от контекста, в котором они появляются: внутри выражения они стоят за соответствующие операторы, но в декларация * обычно появляется как часть типа (что означает "указатель на" ), а = используется для обозначения начала инициализации (копирования) (, разделяет несколько деклараций, & как "ссылка to" также является частью типа).

Ответ 2

int a, *test= &a;

эквивалентно:

int a;
int* test = &a;

и отлично действует при инициализации test, который имеет тип указателя на int с адресом переменной a, который имеет тип int.

Ответ 3

Вы смешиваете два использования для *.

В первом примере вы используете его для разыменования указателя. Во втором примере вы используете его для объявления "указателя на int".

Итак, когда вы используете * в объявлении, он должен сказать, что вы объявляете указатель.

Ответ 4

Фактически вы делаете инициализацию в первом случае,

int *test = &a;

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

Но после инициализации *test (со звездочкой) означает, что вы пытаетесь получить доступ к значению по адресу, назначенному указателю test.
Другими словами, выполнение *test означает, что вы получаете значение a, потому что адрес a хранится в указателе test, который выполняется просто с помощью &a.
& - это оператор для получения адреса любой переменной. И * - это оператор для получения значения по адресу.

Значения инициализации и выводятся по-разному компилятором, даже если в обоих случаях присутствует звездочка *.

Ответ 5

Вы просто ударили по двум ужасным языковым пятнам: сжатие объявлений в одну строку и повторное использование символа * для несвязанных целей. В этом случае * используется для объявления указателя (когда он используется как часть сигнатуры типа int a,*test;) и для обозначения указателя (когда он используется как оператор *test = &a;). Хорошей практикой было бы объявлять переменные по одному, использовать автоматический вывод типа вместо типа copypasting и использовать выделенный метод addressof:

#include <memory> // for std::addressof

int a{};
auto const p_a{::std::addressof(a)};

Ответ 6

Там тонкая разница.

Когда вы объявляете int a, * test, вы говорите "объявляете как целое число и объявляете тест как указатель на целое число, причем оба они неинициализированы".

В первом примере вы устанавливаете * test на & right после деклараций. Это означает: "Установите целое число, на которое указывает контрольные точки (адрес памяти), на адрес". ". Это почти наверняка приведет к сбою, потому что тест не был инициализирован, поэтому он будет либо нулевым указателем, либо тарабарщиной.

В другом примере int a, * test = & a переводит: "объявляет a как неинициализированное целое число и объявляет тест как указатель, инициализированный адресом a." Это верно. Более подробно он переводится на:

int a, *test;
test = &a;