Dereferencing a 2D array

Hello,

In the code below, I am trying to print the data from a 2D array using the dereference operator (*)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

#include<iostream>
using namespace std;


int main (){

    int myArray[5] = {62, 45, 95, 85, 0};
    int array2D[3][3] = {{1,  5,  6},
                        {45, 65, 65},
                        {78, 10, 99}};


     //Test #1, printing using (*) works fine on 1D arrays
    cout << "\nHere, I will print data from the 1D array:"
         << "\nData on [0]: " << *(myArray)
         << "\nData on [4]: " << *(myArray+4);

    
     //Test #2, printing using (*) does not work with 2D arrays
    cout << "\n\nI will print a 2D array"
         << "\n\nFirst, the data on [1][2]: " << *(array2D+1)
         << "\nNow, the data on [2][2]: " << *(array2D+4);

    //Test #3, to see the address
    cout << "\n\nI will print the address of the same two values we used before"
         << "\nAddress of [1][2]: " << (array2D+1)
         << "\nAddress of [2][2]: " << (array2D+4);

    return 0;
}


So, the code on Test#2 will return the address of the data in the array, but will not return the data itself, as it does on Test#1.

I know there are other ways to print the data, but I want to know why using (*) on a 2D array won't work,.

The IDE isn't returning any error or warning, it just prints the address in hexadecimal value instead of the data.

I know I am using the right address, since I tested it on Test#3.

I appreciate you help.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <string>
#include <typeinfo>

#ifdef __GNUG__

    #include <cxxabi.h>
    #include <cstdlib>
    #include <memory>

    template< typename T > std::string type_name()
    {
        int status ;
        std::unique_ptr< char[], decltype(&std::free) > buffer(
            __cxxabiv1::__cxa_demangle( typeid(T).name(), nullptr, 0, &status ), &std::free ) ;
        return status==0 ? buffer.get() : "__cxa_demangle error" ;
    }

#else // !defined __GNUG__

    template< typename T > std::string type_name() { return typeid(T).name() ; }

#endif //__GNUG__

template< typename T > std::string type_name( const T& ) { return type_name<T>() ; }


#define print_type_name(var) ( std::cout << #var << " is of type " << type_name(var) << "\n\n" )

#include <iostream>

int main()
{
    int array2D[3][3] = { { 1,  5,  6 }, { 45, 65, 65}, { 78, 10, 99 } } ;

    auto ptr = array2D+1 ;

    print_type_name( ptr ) ; // ptr is of type int (*) [3]

    print_type_name( *ptr ) ; // *ptr is of type int [3]

}

http://ideone.com/vHL1wW
to better understand analize this:
1
2
3
4
5
6
7
8
	int *p[3]; // array of pointers to arrays
	int a[3] = {1,  5,  6};  //1st row
	int b[3] = {45, 65, 65}; //2nd row
	int c[3] = {78, 10, 99}; //2rd row

	p[0] = a;
	p[1] = b;
	p[2] = c;


so now:
writing p[0] is like writing a, which is array name, which is its address
so *(p+1) is pointer to b, and *(p+2) to c.

(*p)[0] is a[0]
(*p)[1] is a[1]
(*p)[2] is a[2]

(*(p+1))[0] is b[0]
etc.

(*(p+2)) is c address, so *(*(p+2)) is c 1st element.
*((*(p+2)) +2) is c 2nd element

so to gain access to your 2d array:
1
2
3
4
5
6
7
   int array2D[3][3] = {{1,  5,  6},
                       {45, 65, 65},
                       {78, 10, 99}};


	cout << *((*(array2D+2)) +2) << endl <<
			(*array2D)[2] << endl;

so:
*((*(array2D+rowNumber)) +colNumber)

Conculsion:
int myArray[5] use single pointer (*p)
int array2D[3][3] use double pointer (**p)
Last edited on
closed account (D80DSL3A)
I want to know why using (*) on a 2D array won't work,

You must dereference twice to obtain a value. Once obtains an address.

Adapting from your code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
using namespace std;// OK in small programs(?), but generally a bad practice

int main()
{
    int array2D[3][3] = {{1,  5,  6},
                        {45, 65, 75},// changed 2nd 65 to 75 so values are unique
                        {78, 10, 99}};

    cout << "Base address: " << *array2D;
    cout << "\nValue of 1st element: " << **array2D;

    //Test #3, to see the address
    cout << "\n\nI will print the address of the same two values we used before"
         << "\nAddress of [1][2]: " << *(array2D+1)+2
         << "\nAddress of [2][2]: " << *(array2D+2)+2;

        //Test #4, to see values at the address
    cout << "\n\nI will print the values at the same two address we used before"
         << "\nValue of [1][2]: " << *(*(array2D+1)+2)
         << "\nValue of [2][2]: " << *(*(array2D+2)+2);


    cout << endl;
    return 0;
}

Output:
Base address: 0x22ff1c
Value of 1st element: 1

I will print the address of the same two values we used before
Address of [1][2]: 0x22ff30
Address of [2][2]: 0x22ff3c

I will print the values at the same two address we used before
Value of [1][2]: 75
Value of [2][2]: 99
Thanks tath, I got it working flawlessly.

I want to point out that one can also use
*(*(array2D+2)+2

But using
**(array2D+4)
returns garbage (At least it did for me).
Topic archived. No new replies allowed.