maxE
maxE

Reputation: 361

Pointers: initialisation vs. declaration

I am a C++ noob and I am quite sure this is a stupid question, but I just do not quite understand why an error arises (does not arise) from the following code:

#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;
}

But why does this work too?

#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;
}

Upvotes: 17

Views: 1138

Answers (6)

TheWaterProgrammer
TheWaterProgrammer

Reputation: 8239

You are actually doing an initialisation like this in first case,

int *test = &a;

It means that, you are initialising a pointer for which you mention * to tell the compiler that its a pointer.

But after initialisation doing a *test (with an asterisk) means that you are trying to access the value at the address assigned to pointer test.
In other words, doing an *test means you are getting the value of a because address of a is stored into pointer test which is done by just doing a &a.
& is the operator to get the address of any variable. And * is the operator to get the value at address.

So initialisation & assignment are inferred differently by the compiler even if the asterisk * is present in both the cases.

Upvotes: 2

user1258361
user1258361

Reputation: 1133

There's a subtle difference there.

When you declare int a, *test, you're saying "declare a as an integer, and declare test as a pointer to an integer, with both of them uninitialized."

In your first example, you set *test to &a right after the declarations. That translates to: "Set the integer that test points to (the memory address) to the address of a." That will almost certainly crash because test wasn't initialized, so it would either be a null pointer or gibberish.

In the other example, int a, *test= &a translates to: "declare a as an uninitialized integer, and declare test as a pointer initialized to the address of a." That's valid. More verbosely, it translates to:

int a, *test;
test = &a;

Upvotes: 0

Daniel Jour
Daniel Jour

Reputation: 16156

The fundamental difference between those two lines

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

is that the first is an expression, consisting of operator calls with the known precedence rules:

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

whereas the second is a variable declaration and initialization, and equivalent to the declaration of int a; followed by:

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

Neither operator* nor operator= is even used in the second line.

The meaning of the tokens * and = (and & as well as ,) is dependent on the context in which they appear: inside of an expression they stand for the corresponding operators, but in a declaration * usually appears as part of the type (meaning "pointer to") and = is used to mark the beginning of the (copy) initialization expression (, separates multiple declarations, & as "reference to" is also part of the type).

Upvotes: 30

user7860670
user7860670

Reputation: 37520

You just hit two of the horrible language design spots: squeezing declarations into one line and reuse of * symbol for unrelated purposes. In this case * is used to declare a pointer (when it is used as part of type signature int a,*test;) and to deference a pointer (when it is used as a statement *test = &a;). The good practice would be to declare variables one at a time, to use automatic type deduction instead of type copypasting and to use dedicated addressof method:

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

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

Upvotes: 1

haddie
haddie

Reputation: 21

You're confusing two uses for *.

In your first example, you're using it to dereference a pointer. In the second example, you're using it to declare a "pointer to int".

So, when you use * in a declaration, it's there to say that you're declaring a pointer.

Upvotes: 2

Edgar Rokjān
Edgar Rokjān

Reputation: 17483

int a, *test= &a;

is equivalent of:

int a;
int* test = &a;

and perfectly valid as you initialize test which has a type of pointer to int with an address of variable a which has a type of int.

Upvotes: 3

Related Questions