1

Why is the initialization of lp illegal?

int i = 42; 
long *lp = &i;

Xcode prompts that I cannot initialize a variable of type 'long *' with an rvalue of type 'int *'.

Why?

anastaciu
  • 23,467
  • 7
  • 28
  • 53
  • Pointer means exactly what it says, it points to some object, object type is said in the declaration of pointer, if you have variable of type ```long *```, it must have address of ```long``` type object. In case of inheritance and classes this is not the case always, but for built in type, it is. – Karen Melikyan Apr 26 '21 at 09:30

1 Answers1

1

Your Xcode is on point, those are different types, it is indeed an illegal initialization, C++ does not allow for assignment (or initialization) of pointers with different types.

That said, you can explicitly convert the assignee:

int i = 42; 
long *lp = reinterpret_cast<long*>(&i);

About your seach for reasoning, I'll say those are the rules of the language, they are there to protect you (and your program), not to make your job more difficult, a pointer to long used to operate (dereference, increment, etc.) in an address which is used to store an int will invoke undefined behavior. A compiler is not obliged to treat pointers of different types in the same way. Differences in size, alignment, etc. can occur.

As largest_prime_is_463035818 stated the obligation to explicitly cast tries to prevent mistakes.

This, however, only allows you to compile your program, it doesn't remove the possibility of it being ill-formed.

Simple example:

int i = 42;   

int *p = &i;    
long *lp = reinterpret_cast<long*>(&i);
long *lpc = (long*)(&i); 

std::cout << "int pointer => " << *p << "\n";   // fine, prints 42
std::cout << "long pointer => " << *lp << "\n"; // not fine, prints random vaue *
std::cout << "long pointer 2 => " << *lpc << "\n"; // not fine, same *

As you can see in the example above your compiler was right, that is indeed a problematic cast, tricking the compiler to allow the conversion made the program compile, but fail to produce a consistent result.

* I also tried this in a Windows platform and the results were good, maybe because a long in my platform is only 4 bytes, same as an int, maybe not, the point is, you only should do this when you are absolutely certain that the types are interchangeable.

anastaciu
  • 23,467
  • 7
  • 28
  • 53
  • I want to know Why is the initialization of lp illegal? What's the reason, principle? – Chenglong Li Apr 26 '21 at 09:52
  • 1
    @ChenglongLi counter question: Why should it be allowed? If you want to assign a `int*` to a `long*` then chances are high that either you declared one of them as the wrong type or you have a logic error in your code. Forcing you to make it explicit via a cast helps to avoid mistakes, it turns logic errors or typos into compiler errors, which is generally desirable – 463035818_is_not_an_ai Apr 26 '21 at 10:17
  • @ChenglongLi, those are the rules, and they are there to protect you (and your program), a pointer to long used to operate in an address which is used to store an int may cause undefined behavior, a compiler is not obliged to treat pointers of different types in the same way. As largest_prime_is_463035818 an explicit cast makes sure that mistakes are not made, furthermore using reinterpret_cast adds an extra layer of protection, only allowed conversions can be performed. – anastaciu Apr 26 '21 at 10:48
  • @ChenglongLi though not the same subject per se, you can find some useful info here https://stackoverflow.com/q/19710601/6865932 – anastaciu Apr 26 '21 at 10:58
  • @ChenglongLi even if the compiler allowed such an assignment, `int` and `long` are different types and not guaranteed to be the same size, so trying to access an `int` via a `long*` pointer, or access a `long` via an `int*` pointer, would be *undefined behavior*. – Remy Lebeau Apr 26 '21 at 19:52