16

I've been reading C++ Primer 5th edition. It mentions that

It is illegal to assign an int variable to a pointer, even if the variable’s value happens to be 0.

I give it a try, and find the following result:

int *u = 0; // success

int *w = 123; // fail 
/* compile error:
ptr_test.cc:9:12: error: invalid conversion from 'int' to 'int*' [-fpermissive]
    int *w = 123;
*/


int zero = 0;
int *v = zero; // fail
/* compile error
ptr_test.cc:9:12: error: invalid conversion from 'int' to 'int*' [-fpermissive]
    int *w = zero;
*/

Can someone help me explain the exact rule of pointer initialization? Why assigning to a int pointer to 0 is fine, but 123 is not ok, though they are both integer? Why does 123 result in a to "*int" cast, while 0 does not?

BTW, I'm using g++ (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0.

Okd
  • 197
  • 5
  • Look at the link provided by me that explains "Type Casting". – noobmaster69 Jan 04 '20 at 06:50
  • 1
    accepting 0 as null is a convention. When, you try to attribute `zero(=0)` to `*v`, there's an exception too. Because when the compiler parse through `0` that is equals to some pointer, they evaluate the value to be `NULL`. But when you try to make `*v=zero`, the compiler match the types of variables first and find one to be pointer another to be int (this doesn't happen to *v=0 because 0 is handled exceptionally). – noobmaster69 Jan 04 '20 at 06:57
  • Related: [How is 0 distinguished from other integers when initializing nullptr_t?](https://stackoverflow.com/q/33670170/673852) – Ruslan Jan 04 '20 at 15:54

6 Answers6

21

Why assigning to a int pointer to 0 is fine

Because 0, besides being an integer literal, is also a null pointer constant. And a null pointer constant converts to any pointer type.

but 123 is not ok

Because 123, or any other integer literal besides those whose value is 0, is not a null pointer constant. And integer expressions (except for null pointer constants) don't implicitly convert to pointer types.

Why does 123 result in a to "*int" cast, while 0 does not?

Neither "results in a cast". Cast is an explicit conversion, and in these examples all conversions are implicit. Implicit conversion from integer to pointer is ill-formed, which is why you get the error. The null pointer conversion is implicit and well-formed, which is why you don't get an error.

Can someone help me explain the exact rule

Here is the exact rule (quote from the latest C++ standard draft):

[conv.ptr]

A null pointer constant is an integer literal ([lex.icon]) with value zero or a prvalue of type std​::​nullptr_­t. A null pointer constant can be converted to a pointer type; the result is the null pointer value of that type ([basic.compound]) and is distinguishable from every other value of object pointer or function pointer type. Such a conversion is called a null pointer conversion. ...

P.S. The keyword nullptr is a prvalue of type std​::​nullptr_­t. It should always be favoured over using literal 0 except in the case you intend to support pre-C++11 compilers.

eerorika
  • 232,697
  • 12
  • 197
  • 326
14

C++ has a special case for the literal integer 0, which is implicitly convertible to a null pointer.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
3

int *u = 0;is considered as null value. So, it would be a null pointer. The other errors arises from "Type Casting". int *wis declaration of a new int type pointer, so a integer value can't be equal to a pointer. This would give you better idea about what's going on:
https://www.cprogramming.com/tutorial/lesson11.html
Accepting 0 as null is a convention. When, you try to attribute zero(=0) to *v, there's an error occurs too. Because when the compiler parse through 0 that is equals to some pointer, they evaluate the 0 and replace it with NULL. But when you try to make *v=zero, the compiler match the types of variables first and find one to be pointer another to be int (this doesn't happen to *v=0 because 0 is handled exceptionally).

noobmaster69
  • 182
  • 1
  • 3
  • 13
  • 1
    As I remembered, NULL is defined as 0 – Okd Jan 04 '20 at 06:36
  • `int *ptr = NULL` and `int *ptr = 0` produces the same result. Though 0 is int, you can attribute 0 as a value of a pointer and by convention it will be null pointer. – noobmaster69 Jan 04 '20 at 06:39
  • The error is not from "Type Casting". It's from type **conversion**. A cast is something you write in your source code to tell the compiler to do a conversion. – Pete Becker Jan 04 '20 at 15:26
3

Other answers have adequately described the fact that the literal expression 0 can be a null pointer constant. But they haven't come out and explained why your book is also correct. Let's repeat your quotation, with a little highlighting.

It is illegal to assign an int variable to a pointer, even if the variable’s value happens to be 0.

The thing that tripped you up is that 0 is not a variable. That means that the following code is illegal:

int i = 0;   // int variable with value 0
int *ip = i; // nope, won't work

Of course, your book might have misled you by using the word "variable". This is true for all objects, not just the ones with names.

Spencer
  • 1,924
  • 15
  • 27
  • Variable is an official technical term in the C++ Standard: https://timsong-cpp.github.io/cppwp/basic#pre-6 . The statement `int i = 0;` defines a variable, and in the statement `int *ip = i;`, the expression `i` names the same variable. A variable with object type and which has a definition denotes an object, though not every object has a variable. – aschepler Jan 05 '20 at 05:17
2

Why assigning to a int pointer to 0 is fine, but 123 is not ok, though they are both integer?

0 is a special case to allow assigning NULL which was usually defined something like this:
#define NULL 0

In C++11 you may find it defined like this:
#define NULL nullptr

With the C++11 addition nullptr the special case may be removed some time in the future.

Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
2

Here's Stroustrup's take on this: C++ Style and Technique FAQ

In C++, the definition of NULL is 0, so there is only an aesthetic difference. I prefer to avoid macros, so I use 0. Another problem with NULL is that people sometimes mistakenly believe that it is different from 0 and/or not an integer. In pre-standard code, NULL was/is sometimes defined to something unsuitable and therefore had/has to be avoided. That's less common these days.

That is, if you use 0 with pointers, it yields NULL - simply privelage for 0.