1

I have an array of 5 integers. arr and &arr is same address. So why number 2 gives compilation error and and 3 works fine.

  int arr[5] = {1,2,3,4,5};
  1. int *p = arr;
  2. int (*p1)[5] = arr //Compilation Error
  3. int (*p1)[5] = &arr; //Works fine.
  
     arr = 0x61fdf0 and &arr= 0x61fdf0
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
Sanjeev
  • 115
  • 7

2 Answers2

3

The problem is that the initialized object and the initializer have different pointer types and there is no implicit conversion from one pointer type to another.

In this declaration

int (*p1)[5] = arr;

the initialized object has the type int ( * )[5] while the initializer has the type int * due to the implicit conversion of the array designator to a pointer to its first element.

You have to write

int (*p1)[5] = &arr

Or for example

int ( *p1 )[5] = reinterpret_cast<int ( * )[5]>( arr );

Here is a demonstrative program.

#include <iostream>

int main() 
{
    int arr[5] = {1,2,3,4,5};   
    
    int ( *p1 )[5] = reinterpret_cast<int ( * )[5]>( arr );

    std::cout << "sizeof( *p1 ) = " << sizeof( *p1 ) << '\n';
    
    return 0;
}

The program output is

sizeof( *p1 ) = 20

Objects can have equal values but different types.

Consider an another case.

Let's assume that you have an object of a structure type

struct A
{
    int x;
} a;

in this case &a and &a.x have the same values but the types of the expressions are different. You may not write for example

int *p = &a;

the compiler will issue an error. But you can write

int *p = ( int * )&a;

or

int *p = reinterpret_cast<int *>( &a );

Here is a demonstrative program.

#include <iostream>
#include <iomanip>

int main() 
{
    struct A
    {
        int x;
    } a = { 10 };
    
    std::cout << std::boolalpha << ( ( void * )&a.x == ( void * )&a ) << '\n';
    
    int *p = reinterpret_cast<int *>( &a );
    
    std::cout << "*p = " << *p << '\n';
    
    return 0;
}

The program output is

true
*p = 10

As for your one more question in a comment

Can you decode this in simple language to understand int** p = new int*[5];

then in this expression with the operator new

new int*[5]

there is allocated memory for an array with 5 elements of the type int *. The expression returns a pointer to the first element of the array. A pointer to an object of the type int * (the type of elements of the allocated array) will have the type int **.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • Can you decode this in simple language to understand int** p = new int*[5]; – Sanjeev Mar 03 '21 at 15:07
  • Okay.Can you please share your views on this also ? https://stackoverflow.com/questions/66461618/why-cant-we-directly-assign-address-of-a-2d-array-to-pointer – Sanjeev Mar 03 '21 at 17:03
0

To put it simply, it's for the same reason that this throws a compilation error:

int main()
{
    int x = 5;
    int *p = x;
}

When you have a pointer designated for an object type, you're supposed to assign the address of an object of that type. That being said, while the code above doesn't make sense, the code below does:

int main()
{
    int x = 5;
    int *p = &x;
}

This applies to arrays in the same way it applies to anything else.

int main()
{
    int x[5] = {1, 2, 3, 4, 5};
    int (*p)[5] = x; // Compilation error.
    int (*p)[5] = &x; // Does exactly what it should.
}

You are correct in stating that x and &x might very well have the same value, so assigning x to the pointer instead of &x should work and make sense. While it does make sense from a technical perspective, it doesn't make sense from a semantic perspective. The c++ language prioritizes semantics to help the programmer avoid mistakes. Here's an example:

int main()
{
    int x = 0x72fe1c; // Let's imagine that 0x72fe1c just so happens to be the address of x.
    // x is an int variable holding a value which just so happens to be equal to its address.
    int *p = x; // This is never desirable; thank the compiler for telling you something is wrong.
}

The above code makes sense from a technical perspective. x holds a value that happens to be equal to its own memory address, so what's the harm in assigning its value to a pointer? The "harm" lies in the fact that a c++ programmer would never want this in a practical situation because c++ is one level above assembly; you're not supposed to work with memory addresses like that. As such, the compiler forbids you from executing such code to help you avoid mistakes.

GT 77
  • 448
  • 5
  • 12